mirror of
https://github.com/ansible/awx.git
synced 2026-05-20 07:17:40 -02:30
Remove action items from Instance peers list.
This commit is contained in:
@@ -6,16 +6,12 @@ import PaginatedTable, {
|
|||||||
HeaderCell,
|
HeaderCell,
|
||||||
HeaderRow,
|
HeaderRow,
|
||||||
} from 'components/PaginatedTable';
|
} from 'components/PaginatedTable';
|
||||||
import useRequest, { useDismissableError } from 'hooks/useRequest';
|
|
||||||
import { getQSConfig, parseQueryString } from 'util/qs';
|
import { getQSConfig, parseQueryString } from 'util/qs';
|
||||||
import { useLocation, useParams } from 'react-router-dom';
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
|
import useRequest from 'hooks/useRequest';
|
||||||
import DataListToolbar from 'components/DataListToolbar';
|
import DataListToolbar from 'components/DataListToolbar';
|
||||||
import { InstancesAPI } from 'api';
|
import { InstancesAPI } from 'api';
|
||||||
import useExpanded from 'hooks/useExpanded';
|
import useExpanded from 'hooks/useExpanded';
|
||||||
import ErrorDetail from 'components/ErrorDetail';
|
|
||||||
import useSelected from 'hooks/useSelected';
|
|
||||||
import HealthCheckButton from 'components/HealthCheckButton';
|
|
||||||
import AlertModal from 'components/AlertModal';
|
|
||||||
import InstancePeerListItem from './InstancePeerListItem';
|
import InstancePeerListItem from './InstancePeerListItem';
|
||||||
|
|
||||||
const QS_CONFIG = getQSConfig('peer', {
|
const QS_CONFIG = getQSConfig('peer', {
|
||||||
@@ -65,30 +61,6 @@ function InstancePeerList() {
|
|||||||
fetchPeers();
|
fetchPeers();
|
||||||
}, [fetchPeers]);
|
}, [fetchPeers]);
|
||||||
|
|
||||||
const { selected, isAllSelected, handleSelect, clearSelected, selectAll } =
|
|
||||||
useSelected(peers.filter((i) => i.node_type !== 'hop'));
|
|
||||||
|
|
||||||
const {
|
|
||||||
error: healthCheckError,
|
|
||||||
request: fetchHealthCheck,
|
|
||||||
isLoading: isHealthCheckLoading,
|
|
||||||
} = useRequest(
|
|
||||||
useCallback(async () => {
|
|
||||||
await Promise.all(
|
|
||||||
selected
|
|
||||||
.filter(({ node_type }) => node_type !== 'hop')
|
|
||||||
.map(({ instanceId }) => InstancesAPI.healthCheck(instanceId))
|
|
||||||
);
|
|
||||||
fetchPeers();
|
|
||||||
}, [selected, fetchPeers])
|
|
||||||
);
|
|
||||||
const handleHealthCheck = async () => {
|
|
||||||
await fetchHealthCheck();
|
|
||||||
clearSelected();
|
|
||||||
};
|
|
||||||
|
|
||||||
const { error, dismissError } = useDismissableError(healthCheckError);
|
|
||||||
|
|
||||||
const { expanded, isAllExpanded, handleExpand, expandAll } =
|
const { expanded, isAllExpanded, handleExpand, expandAll } =
|
||||||
useExpanded(peers);
|
useExpanded(peers);
|
||||||
|
|
||||||
@@ -96,7 +68,7 @@ function InstancePeerList() {
|
|||||||
<CardBody>
|
<CardBody>
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
contentError={contentError}
|
contentError={contentError}
|
||||||
hasContentLoading={isLoading || isHealthCheckLoading}
|
hasContentLoading={isLoading}
|
||||||
items={peers}
|
items={peers}
|
||||||
itemCount={count}
|
itemCount={count}
|
||||||
pluralizedItemName={t`Peers`}
|
pluralizedItemName={t`Peers`}
|
||||||
@@ -124,51 +96,26 @@ function InstancePeerList() {
|
|||||||
>{t`Name`}</HeaderCell>
|
>{t`Name`}</HeaderCell>
|
||||||
<HeaderCell sortKey="errors">{t`Status`}</HeaderCell>
|
<HeaderCell sortKey="errors">{t`Status`}</HeaderCell>
|
||||||
<HeaderCell sortKey="node_type">{t`Node Type`}</HeaderCell>
|
<HeaderCell sortKey="node_type">{t`Node Type`}</HeaderCell>
|
||||||
<HeaderCell>{t`Capacity Adjustment`}</HeaderCell>
|
|
||||||
<HeaderCell>{t`Used Capacity`}</HeaderCell>
|
|
||||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
}
|
}
|
||||||
renderToolbar={(props) => (
|
renderToolbar={(props) => (
|
||||||
<DataListToolbar
|
<DataListToolbar
|
||||||
{...props}
|
{...props}
|
||||||
isAllSelected={isAllSelected}
|
|
||||||
onSelectAll={selectAll}
|
|
||||||
isAllExpanded={isAllExpanded}
|
isAllExpanded={isAllExpanded}
|
||||||
onExpandAll={expandAll}
|
onExpandAll={expandAll}
|
||||||
qsConfig={QS_CONFIG}
|
qsConfig={QS_CONFIG}
|
||||||
additionalControls={[
|
|
||||||
<HealthCheckButton
|
|
||||||
onClick={handleHealthCheck}
|
|
||||||
selectedItems={selected}
|
|
||||||
/>,
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
renderRow={(peer, index) => (
|
renderRow={(peer, index) => (
|
||||||
<InstancePeerListItem
|
<InstancePeerListItem
|
||||||
onSelect={() => handleSelect(peer)}
|
|
||||||
isSelected={selected.some((row) => row.id === peer.id)}
|
|
||||||
isExpanded={expanded.some((row) => row.id === peer.id)}
|
isExpanded={expanded.some((row) => row.id === peer.id)}
|
||||||
onExpand={() => handleExpand(peer)}
|
onExpand={() => handleExpand(peer)}
|
||||||
key={peer.id}
|
key={peer.id}
|
||||||
peerInstance={peer}
|
peerInstance={peer}
|
||||||
rowIndex={index}
|
rowIndex={index}
|
||||||
fetchInstance={fetchPeers}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{error && (
|
|
||||||
<AlertModal
|
|
||||||
isOpen={error}
|
|
||||||
onClose={dismissError}
|
|
||||||
title={t`Error!`}
|
|
||||||
variant="error"
|
|
||||||
>
|
|
||||||
{t`Failed to run a health check on one or more peers.`}
|
|
||||||
<ErrorDetail error={error} />
|
|
||||||
</AlertModal>
|
|
||||||
)}
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,104 +1,20 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { t, Plural } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import styled from 'styled-components';
|
|
||||||
import 'styled-components/macro';
|
import 'styled-components/macro';
|
||||||
import {
|
import { Tooltip } from '@patternfly/react-core';
|
||||||
Progress,
|
|
||||||
ProgressMeasureLocation,
|
|
||||||
ProgressSize,
|
|
||||||
Slider,
|
|
||||||
Tooltip,
|
|
||||||
} from '@patternfly/react-core';
|
|
||||||
import { Tr, Td, ExpandableRowContent } from '@patternfly/react-table';
|
import { Tr, Td, ExpandableRowContent } from '@patternfly/react-table';
|
||||||
import { formatDateString } from 'util/dates';
|
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';
|
import StatusLabel from 'components/StatusLabel';
|
||||||
import useRequest, { useDismissableError } from 'hooks/useRequest';
|
|
||||||
import useDebounce from 'hooks/useDebounce';
|
|
||||||
import { InstancesAPI } from 'api';
|
|
||||||
import { useConfig } from 'contexts/Config';
|
|
||||||
import AlertModal from 'components/AlertModal';
|
|
||||||
import ErrorDetail from 'components/ErrorDetail';
|
|
||||||
import { Detail, DetailList } from 'components/DetailList';
|
import { Detail, DetailList } from 'components/DetailList';
|
||||||
|
|
||||||
const Unavailable = styled.span`
|
|
||||||
color: var(--pf-global--danger-color--200);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SliderHolder = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SliderForks = styled.div`
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-right: 8px;
|
|
||||||
margin-left: 8px;
|
|
||||||
text-align: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
function InstancePeerListItem({
|
function InstancePeerListItem({
|
||||||
peerInstance,
|
peerInstance,
|
||||||
fetchInstances,
|
|
||||||
isSelected,
|
|
||||||
onSelect,
|
|
||||||
isExpanded,
|
isExpanded,
|
||||||
onExpand,
|
onExpand,
|
||||||
rowIndex,
|
rowIndex,
|
||||||
}) {
|
}) {
|
||||||
const { me = {} } = useConfig();
|
|
||||||
const [forks, setForks] = useState(
|
|
||||||
computeForks(
|
|
||||||
peerInstance.mem_capacity,
|
|
||||||
peerInstance.cpu_capacity,
|
|
||||||
peerInstance.capacity_adjustment
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const labelId = `check-action-${peerInstance.id}`;
|
const labelId = `check-action-${peerInstance.id}`;
|
||||||
|
|
||||||
function usedCapacity(item) {
|
|
||||||
if (item.enabled) {
|
|
||||||
return (
|
|
||||||
<Progress
|
|
||||||
value={Math.round(100 - item.percent_capacity_remaining)}
|
|
||||||
measureLocation={ProgressMeasureLocation.top}
|
|
||||||
size={ProgressSize.sm}
|
|
||||||
title={t`Used capacity`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return <Unavailable>{t`Unavailable`}</Unavailable>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { error: updateInstanceError, request: updateInstance } = useRequest(
|
|
||||||
useCallback(
|
|
||||||
async (values) => {
|
|
||||||
await InstancesAPI.update(peerInstance.id, values);
|
|
||||||
},
|
|
||||||
[peerInstance]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const { error: updateError, dismissError: dismissUpdateError } =
|
|
||||||
useDismissableError(updateInstanceError);
|
|
||||||
|
|
||||||
const debounceUpdateInstance = useDebounce(updateInstance, 200);
|
|
||||||
|
|
||||||
const handleChangeValue = (value) => {
|
|
||||||
const roundedValue = Math.round(value * 100) / 100;
|
|
||||||
setForks(
|
|
||||||
computeForks(
|
|
||||||
peerInstance.mem_capacity,
|
|
||||||
peerInstance.cpu_capacity,
|
|
||||||
roundedValue
|
|
||||||
)
|
|
||||||
);
|
|
||||||
debounceUpdateInstance({ capacity_adjustment: roundedValue });
|
|
||||||
};
|
|
||||||
const isHopNode = peerInstance.node_type === 'hop';
|
const isHopNode = peerInstance.node_type === 'hop';
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -117,15 +33,7 @@ function InstancePeerListItem({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Td
|
<Td />
|
||||||
select={{
|
|
||||||
rowIndex,
|
|
||||||
isSelected,
|
|
||||||
onSelect,
|
|
||||||
disable: isHopNode,
|
|
||||||
}}
|
|
||||||
dataLabel={t`Selected`}
|
|
||||||
/>
|
|
||||||
<Td id={labelId} dataLabel={t`Name`}>
|
<Td id={labelId} dataLabel={t`Name`}>
|
||||||
<Link to={`/instances/${peerInstance.id}/details`}>
|
<Link to={`/instances/${peerInstance.id}/details`}>
|
||||||
<b>{peerInstance.hostname}</b>
|
<b>{peerInstance.hostname}</b>
|
||||||
@@ -149,51 +57,6 @@ function InstancePeerListItem({
|
|||||||
</Td>
|
</Td>
|
||||||
|
|
||||||
<Td dataLabel={t`Node Type`}>{peerInstance.node_type}</Td>
|
<Td dataLabel={t`Node Type`}>{peerInstance.node_type}</Td>
|
||||||
{!isHopNode && (
|
|
||||||
<>
|
|
||||||
<Td dataLabel={t`Capacity Adjustment`}>
|
|
||||||
<SliderHolder data-cy="slider-holder">
|
|
||||||
<div data-cy="cpu-capacity">{t`CPU ${peerInstance.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={peerInstance.capacity_adjustment}
|
|
||||||
onChange={handleChangeValue}
|
|
||||||
isDisabled={!me?.is_superuser || !peerInstance?.enabled}
|
|
||||||
data-cy="slider"
|
|
||||||
/>
|
|
||||||
</SliderForks>
|
|
||||||
<div data-cy="mem-capacity">{t`RAM ${peerInstance.mem_capacity}`}</div>
|
|
||||||
</SliderHolder>
|
|
||||||
</Td>
|
|
||||||
|
|
||||||
<Td
|
|
||||||
dataLabel={t`Instance group used capacity`}
|
|
||||||
css="--pf-c-table--cell--MinWidth: 175px;"
|
|
||||||
>
|
|
||||||
{usedCapacity(peerInstance)}
|
|
||||||
</Td>
|
|
||||||
|
|
||||||
<ActionsTd
|
|
||||||
dataLabel={t`Actions`}
|
|
||||||
css="--pf-c-table--cell--Width: 125px"
|
|
||||||
>
|
|
||||||
<ActionItem visible>
|
|
||||||
<InstanceToggle
|
|
||||||
css="display: inline-flex;"
|
|
||||||
fetchInstances={fetchInstances}
|
|
||||||
instance={peerInstance}
|
|
||||||
/>
|
|
||||||
</ActionItem>
|
|
||||||
</ActionsTd>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Tr>
|
</Tr>
|
||||||
{!isHopNode && (
|
{!isHopNode && (
|
||||||
<Tr
|
<Tr
|
||||||
@@ -229,17 +92,6 @@ function InstancePeerListItem({
|
|||||||
</Td>
|
</Td>
|
||||||
</Tr>
|
</Tr>
|
||||||
)}
|
)}
|
||||||
{updateError && (
|
|
||||||
<AlertModal
|
|
||||||
variant="error"
|
|
||||||
title={t`Error!`}
|
|
||||||
isOpen
|
|
||||||
onClose={dismissUpdateError}
|
|
||||||
>
|
|
||||||
{t`Failed to update capacity adjustment.`}
|
|
||||||
<ErrorDetail error={updateError} />
|
|
||||||
</AlertModal>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user