mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-14 15:58:38 -05:00
Refactor the health check button
This commit is contained in:
@@ -5,37 +5,26 @@ import { useKebabifiedMenu } from 'contexts/Kebabified';
|
||||
|
||||
function HealthCheckButton({ isDisabled, onClick, selectedItems }) {
|
||||
const { isKebabified } = useKebabifiedMenu();
|
||||
const hopNodeSelected =
|
||||
selectedItems.filter((instance) => instance.node_type === 'hop').length > 0;
|
||||
const hasSelectedItems = selectedItems.length > 0;
|
||||
|
||||
const buildTooltip = () => {
|
||||
if (hopNodeSelected) {
|
||||
return (
|
||||
<Plural
|
||||
value={hopNodeSelected}
|
||||
one="Cannot run health check on a hop node. Deselect the hop node to run a health check."
|
||||
other="Cannot run health check on hop nodes. Deselect the hop nodes to run health checks."
|
||||
/>
|
||||
);
|
||||
}
|
||||
return selectedItems.length ? (
|
||||
const selectedItemsCount = selectedItems.length;
|
||||
|
||||
const buildTooltip = () =>
|
||||
selectedItemsCount ? (
|
||||
<Plural
|
||||
value={selectedItems.length}
|
||||
value={selectedItemsCount}
|
||||
one="Click to run a health check on the selected instance."
|
||||
other="Click to run a health check on the selected instances."
|
||||
/>
|
||||
) : (
|
||||
t`Select an instance to run a health check.`
|
||||
);
|
||||
};
|
||||
|
||||
if (isKebabified) {
|
||||
return (
|
||||
<Tooltip data-cy="healthCheckTooltip" content={buildTooltip()}>
|
||||
<DropdownItem
|
||||
key="approve"
|
||||
isDisabled={hopNodeSelected || isDisabled || !hasSelectedItems}
|
||||
isDisabled={isDisabled || !selectedItemsCount}
|
||||
component="button"
|
||||
onClick={onClick}
|
||||
ouiaId="health-check"
|
||||
@@ -49,7 +38,7 @@ function HealthCheckButton({ isDisabled, onClick, selectedItems }) {
|
||||
<Tooltip data-cy="healthCheckTooltip" content={buildTooltip()}>
|
||||
<div>
|
||||
<Button
|
||||
isDisabled={hopNodeSelected || isDisabled || !hasSelectedItems}
|
||||
isDisabled={isDisabled || !selectedItemsCount}
|
||||
variant="secondary"
|
||||
ouiaId="health-check"
|
||||
onClick={onClick}
|
||||
|
||||
@@ -69,6 +69,7 @@ export function HeaderCell({
|
||||
idPrefix,
|
||||
className,
|
||||
children,
|
||||
tooltip,
|
||||
}) {
|
||||
const sort = sortKey
|
||||
? {
|
||||
@@ -79,6 +80,11 @@ export function HeaderCell({
|
||||
: null;
|
||||
return (
|
||||
<Th
|
||||
info={
|
||||
tooltip && {
|
||||
popover: <div>{tooltip}</div>,
|
||||
}
|
||||
}
|
||||
id={sortKey ? `${idPrefix}-${sortKey}` : null}
|
||||
className={className}
|
||||
sort={sort}
|
||||
|
||||
+450
-427
File diff suppressed because it is too large
Load Diff
+450
-427
File diff suppressed because it is too large
Load Diff
+450
-427
File diff suppressed because it is too large
Load Diff
+450
-427
File diff suppressed because it is too large
Load Diff
+450
-427
File diff suppressed because it is too large
Load Diff
+450
-427
File diff suppressed because it is too large
Load Diff
+450
-427
File diff suppressed because it is too large
Load Diff
@@ -88,10 +88,14 @@ function InstanceList() {
|
||||
useCallback(async () => {
|
||||
await Promise.all(selected.map(({ id }) => InstancesAPI.healthCheck(id)));
|
||||
fetchInstances();
|
||||
clearSelected();
|
||||
}, [selected, clearSelected, fetchInstances])
|
||||
}, [selected, fetchInstances])
|
||||
);
|
||||
|
||||
const handleHealthCheck = async () => {
|
||||
await fetchHealthCheck();
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const {
|
||||
isLoading: isDisassociateLoading,
|
||||
deleteItems: disassociateInstances,
|
||||
@@ -231,7 +235,7 @@ function InstanceList() {
|
||||
/>,
|
||||
<HealthCheckButton
|
||||
isDisabled={!canAdd}
|
||||
onClick={fetchHealthCheck}
|
||||
onClick={handleHealthCheck}
|
||||
selectedItems={selected}
|
||||
/>,
|
||||
]}
|
||||
@@ -250,7 +254,7 @@ function InstanceList() {
|
||||
<HeaderCell sortKey="hostname">{t`Name`}</HeaderCell>
|
||||
<HeaderCell sortKey="errors">{t`Status`}</HeaderCell>
|
||||
<HeaderCell sortKey="node_type">{t`Node Type`}</HeaderCell>
|
||||
<HeaderCell sortKey="capacity_adjustment">{t`Capacity Adjustment`}</HeaderCell>
|
||||
<HeaderCell>{t`Capacity Adjustment`}</HeaderCell>
|
||||
<HeaderCell>{t`Used Capacity`}</HeaderCell>
|
||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
|
||||
@@ -19,6 +19,7 @@ import StatusLabel from 'components/StatusLabel';
|
||||
import { Instance } from 'types';
|
||||
import useRequest, { useDismissableError } from 'hooks/useRequest';
|
||||
import useDebounce from 'hooks/useDebounce';
|
||||
import computeForks from 'util/computeForks';
|
||||
import { InstancesAPI } from 'api';
|
||||
import { useConfig } from 'contexts/Config';
|
||||
import AlertModal from 'components/AlertModal';
|
||||
@@ -42,15 +43,6 @@ const SliderForks = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
function computeForks(memCapacity, cpuCapacity, selectedCapacityAdjustment) {
|
||||
const minCapacity = Math.min(memCapacity, cpuCapacity);
|
||||
const maxCapacity = Math.max(memCapacity, cpuCapacity);
|
||||
|
||||
return Math.floor(
|
||||
minCapacity + (maxCapacity - minCapacity) * selectedCapacityAdjustment
|
||||
);
|
||||
}
|
||||
|
||||
function InstanceListItem({
|
||||
instance,
|
||||
isExpanded,
|
||||
@@ -196,13 +188,23 @@ function InstanceListItem({
|
||||
<Td colSpan={7}>
|
||||
<ExpandableRowContent>
|
||||
<DetailList>
|
||||
<Detail value={instance.jobs_running} label={t`Running Jobs`} />
|
||||
<Detail value={instance.jobs_total} label={t`Total Jobs`} />
|
||||
<Detail
|
||||
data-cy="running-jobs"
|
||||
value={instance.jobs_running}
|
||||
label={t`Running Jobs`}
|
||||
/>
|
||||
<Detail
|
||||
data-cy="total-jobs"
|
||||
value={instance.jobs_total}
|
||||
label={t`Total Jobs`}
|
||||
/>
|
||||
<Detail
|
||||
data-cy="policy-type"
|
||||
label={t`Policy Type`}
|
||||
value={instance.managed_by_policy ? t`Auto` : t`Manual`}
|
||||
/>
|
||||
<Detail
|
||||
data-cy="last-health-check"
|
||||
label={t`Last Health Check`}
|
||||
value={formatDateString(instance.last_health_check)}
|
||||
/>
|
||||
|
||||
@@ -33,7 +33,6 @@ function Instance({ setBreadcrumb }) {
|
||||
<Route path="/instances/:id/details" key="details">
|
||||
<InstanceDetail setBreadcrumb={setBreadcrumb} />
|
||||
</Route>
|
||||
,
|
||||
<Route path="*" key="not-found">
|
||||
<ContentError isNotFound>
|
||||
{match.params.id && (
|
||||
@@ -49,5 +48,4 @@ function Instance({ setBreadcrumb }) {
|
||||
);
|
||||
}
|
||||
|
||||
export { Instance as _Instance };
|
||||
export default Instance;
|
||||
|
||||
@@ -134,124 +134,122 @@ function InstanceDetail({ setBreadcrumb }) {
|
||||
}
|
||||
const isHopNode = instance.node_type === 'hop';
|
||||
return (
|
||||
<>
|
||||
<CardBody>
|
||||
<DetailList gutter="sm">
|
||||
<Detail
|
||||
label={t`Host Name`}
|
||||
value={instance.hostname}
|
||||
dataCy="instance-detail-name"
|
||||
/>
|
||||
<Detail
|
||||
label={t`Status`}
|
||||
value={
|
||||
<StatusLabel status={healthCheck?.errors ? 'error' : 'healthy'} />
|
||||
}
|
||||
/>
|
||||
<Detail label={t`Node Type`} value={instance.node_type} />
|
||||
{!isHopNode && (
|
||||
<>
|
||||
<Detail
|
||||
label={t`Policy Type`}
|
||||
value={instance.managed_by_policy ? t`Auto` : t`Manual`}
|
||||
/>
|
||||
<Detail label={t`Running Jobs`} value={instance.jobs_running} />
|
||||
<Detail label={t`Total Jobs`} value={instance.jobs_total} />
|
||||
<Detail
|
||||
label={t`Last Health Check`}
|
||||
value={formatDateString(healthCheck?.last_health_check)}
|
||||
/>
|
||||
<Detail
|
||||
label={t`Capacity Adjustment`}
|
||||
value={
|
||||
<SliderHolder data-cy="slider-holder">
|
||||
<div data-cy="cpu-capacity">{t`CPU ${instance.cpu_capacity}`}</div>
|
||||
<SliderForks data-cy="slider-forks">
|
||||
<div data-cy="number-forks">
|
||||
<Plural value={forks} one="# fork" other="# forks" />
|
||||
</div>
|
||||
<Slider
|
||||
areCustomStepsContinuous
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
value={instance.capacity_adjustment}
|
||||
onChange={handleChangeValue}
|
||||
isDisabled={!me?.is_superuser || !instance.enabled}
|
||||
data-cy="slider"
|
||||
/>
|
||||
</SliderForks>
|
||||
<div data-cy="mem-capacity">{t`RAM ${instance.mem_capacity}`}</div>
|
||||
</SliderHolder>
|
||||
}
|
||||
/>
|
||||
<Detail
|
||||
label={t`Used Capacity`}
|
||||
value={
|
||||
instance.enabled ? (
|
||||
<Progress
|
||||
title={t`Used capacity`}
|
||||
value={Math.round(
|
||||
100 - instance.percent_capacity_remaining
|
||||
)}
|
||||
measureLocation={ProgressMeasureLocation.top}
|
||||
size={ProgressSize.sm}
|
||||
aria-label={t`Used capacity`}
|
||||
/>
|
||||
) : (
|
||||
<Unavailable>{t`Unavailable`}</Unavailable>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{healthCheck?.errors && (
|
||||
<CardBody>
|
||||
<DetailList gutter="sm">
|
||||
<Detail
|
||||
label={t`Host Name`}
|
||||
value={instance.hostname}
|
||||
dataCy="instance-detail-name"
|
||||
/>
|
||||
<Detail
|
||||
label={t`Status`}
|
||||
value={
|
||||
<StatusLabel status={healthCheck?.errors ? 'error' : 'healthy'} />
|
||||
}
|
||||
/>
|
||||
<Detail label={t`Node Type`} value={instance.node_type} />
|
||||
{!isHopNode && (
|
||||
<>
|
||||
<Detail
|
||||
fullWidth
|
||||
label={t`Errors`}
|
||||
label={t`Policy Type`}
|
||||
value={instance.managed_by_policy ? t`Auto` : t`Manual`}
|
||||
/>
|
||||
<Detail label={t`Running Jobs`} value={instance.jobs_running} />
|
||||
<Detail label={t`Total Jobs`} value={instance.jobs_total} />
|
||||
<Detail
|
||||
label={t`Last Health Check`}
|
||||
value={formatDateString(healthCheck?.last_health_check)}
|
||||
/>
|
||||
<Detail
|
||||
label={t`Capacity Adjustment`}
|
||||
value={
|
||||
<CodeBlock>
|
||||
<CodeBlockCode>{healthCheck?.errors}</CodeBlockCode>
|
||||
</CodeBlock>
|
||||
<SliderHolder data-cy="slider-holder">
|
||||
<div data-cy="cpu-capacity">{t`CPU ${instance.cpu_capacity}`}</div>
|
||||
<SliderForks data-cy="slider-forks">
|
||||
<div data-cy="number-forks">
|
||||
<Plural value={forks} one="# fork" other="# forks" />
|
||||
</div>
|
||||
<Slider
|
||||
areCustomStepsContinuous
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
value={instance.capacity_adjustment}
|
||||
onChange={handleChangeValue}
|
||||
isDisabled={!me?.is_superuser || !instance.enabled}
|
||||
data-cy="slider"
|
||||
/>
|
||||
</SliderForks>
|
||||
<div data-cy="mem-capacity">{t`RAM ${instance.mem_capacity}`}</div>
|
||||
</SliderHolder>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</DetailList>
|
||||
{!isHopNode && (
|
||||
<CardActionsRow>
|
||||
<Tooltip content={t`Run a health check on the instance`}>
|
||||
<Button
|
||||
isDisabled={!me.is_superuser}
|
||||
variant="primary"
|
||||
ouiaId="health-check-button"
|
||||
onClick={fetchHealthCheck}
|
||||
>
|
||||
{t`Health Check`}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<InstanceToggle
|
||||
css="display: inline-flex;"
|
||||
fetchInstances={fetchDetails}
|
||||
instance={instance}
|
||||
<Detail
|
||||
label={t`Used Capacity`}
|
||||
value={
|
||||
instance.enabled ? (
|
||||
<Progress
|
||||
title={t`Used capacity`}
|
||||
value={Math.round(
|
||||
100 - instance.percent_capacity_remaining
|
||||
)}
|
||||
measureLocation={ProgressMeasureLocation.top}
|
||||
size={ProgressSize.sm}
|
||||
aria-label={t`Used capacity`}
|
||||
/>
|
||||
) : (
|
||||
<Unavailable>{t`Unavailable`}</Unavailable>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</CardActionsRow>
|
||||
</>
|
||||
)}
|
||||
{healthCheck?.errors && (
|
||||
<Detail
|
||||
fullWidth
|
||||
label={t`Errors`}
|
||||
value={
|
||||
<CodeBlock>
|
||||
<CodeBlockCode>{healthCheck?.errors}</CodeBlockCode>
|
||||
</CodeBlock>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</DetailList>
|
||||
{!isHopNode && (
|
||||
<CardActionsRow>
|
||||
<Tooltip content={t`Run a health check on the instance`}>
|
||||
<Button
|
||||
isDisabled={!me.is_superuser}
|
||||
variant="primary"
|
||||
ouiaId="health-check-button"
|
||||
onClick={fetchHealthCheck}
|
||||
>
|
||||
{t`Health Check`}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<InstanceToggle
|
||||
css="display: inline-flex;"
|
||||
fetchInstances={fetchDetails}
|
||||
instance={instance}
|
||||
/>
|
||||
</CardActionsRow>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<AlertModal
|
||||
isOpen={error}
|
||||
onClose={dismissError}
|
||||
title={t`Error!`}
|
||||
variant="error"
|
||||
>
|
||||
{updateInstanceError
|
||||
? t`Failed to update capacity adjustment.`
|
||||
: t`Failed to disassociate one or more instances.`}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
)}
|
||||
</CardBody>
|
||||
</>
|
||||
{error && (
|
||||
<AlertModal
|
||||
isOpen={error}
|
||||
onClose={dismissError}
|
||||
title={t`Error!`}
|
||||
variant="error"
|
||||
>
|
||||
{updateInstanceError
|
||||
? t`Failed to update capacity adjustment.`
|
||||
: t`Failed to disassociate one or more instances.`}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
)}
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ function InstanceList() {
|
||||
);
|
||||
|
||||
const { selected, isAllSelected, handleSelect, clearSelected, selectAll } =
|
||||
useSelected(instances);
|
||||
useSelected(instances.filter((i) => i.node_type !== 'hop'));
|
||||
|
||||
useEffect(() => {
|
||||
fetchInstances();
|
||||
@@ -79,15 +79,16 @@ function InstanceList() {
|
||||
.map(({ id }) => InstancesAPI.healthCheck(id))
|
||||
);
|
||||
fetchInstances();
|
||||
clearSelected();
|
||||
}, [selected, clearSelected, fetchInstances])
|
||||
}, [selected, fetchInstances])
|
||||
);
|
||||
|
||||
const handleHealthCheck = async () => {
|
||||
await fetchHealthCheck();
|
||||
clearSelected();
|
||||
};
|
||||
const { error, dismissError } = useDismissableError(healthCheckError);
|
||||
|
||||
const { expanded, isAllExpanded, handleExpand, expandAll } =
|
||||
useExpanded(instances);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageSection>
|
||||
@@ -135,7 +136,7 @@ function InstanceList() {
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
<HealthCheckButton
|
||||
onClick={fetchHealthCheck}
|
||||
onClick={handleHealthCheck}
|
||||
selectedItems={selected}
|
||||
/>,
|
||||
]}
|
||||
@@ -143,10 +144,13 @@ function InstanceList() {
|
||||
)}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG} isExpandable>
|
||||
<HeaderCell sortKey="hostname">{t`Name`}</HeaderCell>
|
||||
<HeaderCell
|
||||
tooltip={t`Cannot run health check on hop nodes.`}
|
||||
sortKey="hostname"
|
||||
>{t`Name`}</HeaderCell>
|
||||
<HeaderCell sortKey="errors">{t`Status`}</HeaderCell>
|
||||
<HeaderCell sortKey="node_type">{t`Node Type`}</HeaderCell>
|
||||
<HeaderCell sortKey="capacity_adjustment">{t`Capacity Adjustment`}</HeaderCell>
|
||||
<HeaderCell>{t`Capacity Adjustment`}</HeaderCell>
|
||||
<HeaderCell>{t`Used Capacity`}</HeaderCell>
|
||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
|
||||
@@ -152,13 +152,6 @@ describe('<InstanceList/>', () => {
|
||||
wrapper.find('DataListToolbar').prop('onSelectAll')(instances)
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
// Ensures health check button is disabled because a hop node is among
|
||||
// the selected.
|
||||
expect(
|
||||
wrapper.find('Button[ouiaId="health-check"]').prop('isDisabled')
|
||||
).toBe(true);
|
||||
|
||||
await act(async () =>
|
||||
wrapper.find('input[aria-label="Select row 3"]').prop('onChange')(false)
|
||||
);
|
||||
@@ -197,17 +190,4 @@ describe('<InstanceList/>', () => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('AlertModal')).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('Health check button should remain disabled', async () => {
|
||||
await act(async () =>
|
||||
wrapper.find('input[aria-label="Select row 3"]').prop('onChange')(true)
|
||||
);
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('Button[ouiaId="health-check"]').prop('isDisabled')
|
||||
).toBe(true);
|
||||
expect(wrapper.find('Tooltip[data-cy="healthCheckTooltip"]').length).toBe(
|
||||
1
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from '@patternfly/react-core';
|
||||
import { Tr, Td, ExpandableRowContent } from '@patternfly/react-table';
|
||||
import { formatDateString } from 'util/dates';
|
||||
import computeForks from 'util/computeForks';
|
||||
import { ActionsTd, ActionItem } from 'components/PaginatedTable';
|
||||
import InstanceToggle from 'components/InstanceToggle';
|
||||
import StatusLabel from 'components/StatusLabel';
|
||||
@@ -42,15 +43,6 @@ const SliderForks = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
function computeForks(memCapacity, cpuCapacity, selectedCapacityAdjustment) {
|
||||
const minCapacity = Math.min(memCapacity, cpuCapacity);
|
||||
const maxCapacity = Math.max(memCapacity, cpuCapacity);
|
||||
|
||||
return Math.floor(
|
||||
minCapacity + (maxCapacity - minCapacity) * selectedCapacityAdjustment
|
||||
);
|
||||
}
|
||||
|
||||
function InstanceListItem({
|
||||
instance,
|
||||
isExpanded,
|
||||
@@ -120,7 +112,6 @@ function InstanceListItem({
|
||||
expand={{
|
||||
rowIndex,
|
||||
isExpanded,
|
||||
disabled: isHopNode,
|
||||
onToggle: onExpand,
|
||||
}}
|
||||
/>
|
||||
@@ -130,6 +121,7 @@ function InstanceListItem({
|
||||
rowIndex,
|
||||
isSelected,
|
||||
onSelect,
|
||||
disable: isHopNode,
|
||||
}}
|
||||
dataLabel={t`Selected`}
|
||||
/>
|
||||
@@ -138,21 +130,23 @@ function InstanceListItem({
|
||||
<b>{instance.hostname}</b>
|
||||
</Link>
|
||||
</Td>
|
||||
{!instance.node_type !== 'hop' && (
|
||||
<Td dataLabel={t`Status`}>
|
||||
<Tooltip
|
||||
content={
|
||||
<div>
|
||||
{t`Last Health Check`}
|
||||
|
||||
{formatDateString(instance.last_health_check)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<StatusLabel status={instance.errors ? 'error' : 'healthy'} />
|
||||
</Tooltip>
|
||||
</Td>
|
||||
)}
|
||||
|
||||
<Td dataLabel={t`Status`}>
|
||||
<Tooltip
|
||||
content={
|
||||
<div>
|
||||
{t`Last Health Check`}
|
||||
|
||||
{formatDateString(
|
||||
instance.last_health_check ?? instance.last_seen
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<StatusLabel status={instance.errors ? 'error' : 'healthy'} />
|
||||
</Tooltip>
|
||||
</Td>
|
||||
|
||||
<Td dataLabel={t`Node Type`}>{instance.node_type}</Td>
|
||||
{!isHopNode && (
|
||||
<>
|
||||
@@ -209,13 +203,23 @@ function InstanceListItem({
|
||||
<Td colSpan={7}>
|
||||
<ExpandableRowContent>
|
||||
<DetailList>
|
||||
<Detail value={instance.jobs_running} label={t`Running Jobs`} />
|
||||
<Detail value={instance.jobs_total} label={t`Total Jobs`} />
|
||||
<Detail
|
||||
data-cy="running-jobs"
|
||||
value={instance.jobs_running}
|
||||
label={t`Running Jobs`}
|
||||
/>
|
||||
<Detail
|
||||
data-cy="total-jobs"
|
||||
value={instance.jobs_total}
|
||||
label={t`Total Jobs`}
|
||||
/>
|
||||
<Detail
|
||||
data-cy="policy-type"
|
||||
label={t`Policy Type`}
|
||||
value={instance.managed_by_policy ? t`Auto` : t`Manual`}
|
||||
/>
|
||||
<Detail
|
||||
data-cy="last-health-check"
|
||||
label={t`Last Health Check`}
|
||||
value={formatDateString(instance.last_health_check)}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export default function computeForks(
|
||||
memCapacity,
|
||||
cpuCapacity,
|
||||
selectedCapacityAdjustment
|
||||
) {
|
||||
const minCapacity = Math.min(memCapacity, cpuCapacity);
|
||||
const maxCapacity = Math.max(memCapacity, cpuCapacity);
|
||||
|
||||
return Math.floor(
|
||||
minCapacity + (maxCapacity - minCapacity) * selectedCapacityAdjustment
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user