This commit is contained in:
Zita Nemeckova
2023-02-28 12:08:06 +01:00
committed by John Westcott IV
parent 5be90fd36b
commit c20e8eb712
6 changed files with 131 additions and 120 deletions

View File

@@ -88,8 +88,8 @@ function DataListToolbar({
[setIsKebabModalOpen] [setIsKebabModalOpen]
); );
const columns = [...searchColumns]; const columns = [...searchColumns];
if ( !advancedSearchDisabled ) { if (!advancedSearchDisabled) {
columns.push({ name: t`Advanced`, key: 'advanced' }); columns.push({ name: t`Advanced`, key: 'advanced' });
} }
return ( return (
<Toolbar <Toolbar
@@ -226,7 +226,7 @@ DataListToolbar.propTypes = {
additionalControls: PropTypes.arrayOf(PropTypes.node), additionalControls: PropTypes.arrayOf(PropTypes.node),
enableNegativeFiltering: PropTypes.bool, enableNegativeFiltering: PropTypes.bool,
enableRelatedFuzzyFiltering: PropTypes.bool, enableRelatedFuzzyFiltering: PropTypes.bool,
advancedSearchDisabled : PropTypes.bool, advancedSearchDisabled: PropTypes.bool,
}; };
DataListToolbar.defaultProps = { DataListToolbar.defaultProps = {

View File

@@ -56,11 +56,11 @@ function getRouteConfig(userProfile = {}) {
path: '/workflow_approvals', path: '/workflow_approvals',
screen: WorkflowApprovals, screen: WorkflowApprovals,
}, },
{ {
title: <Trans>Host Metrics</Trans>, title: <Trans>Host Metrics</Trans>,
path: '/host_metrics', path: '/host_metrics',
screen: HostMetrics, screen: HostMetrics,
}, },
], ],
}, },
{ {

View File

@@ -1,5 +1,5 @@
import React, {useCallback, useEffect, useState} from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import {t} from "@lingui/macro"; import { t } from '@lingui/macro';
import ScreenHeader from 'components/ScreenHeader/ScreenHeader'; import ScreenHeader from 'components/ScreenHeader/ScreenHeader';
import { HostMetricsAPI } from 'api'; import { HostMetricsAPI } from 'api';
import useRequest from 'hooks/useRequest'; import useRequest from 'hooks/useRequest';
@@ -9,17 +9,17 @@ import PaginatedTable, {
} from 'components/PaginatedTable'; } from 'components/PaginatedTable';
import DataListToolbar from 'components/DataListToolbar'; import DataListToolbar from 'components/DataListToolbar';
import { getQSConfig, parseQueryString } from 'util/qs'; import { getQSConfig, parseQueryString } from 'util/qs';
import {Card, PageSection} from "@patternfly/react-core"; import { Card, PageSection } from '@patternfly/react-core';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import useSelected from 'hooks/useSelected'; import useSelected from 'hooks/useSelected';
import HostMetricsListItem from "./HostMetricsListItem"; import HostMetricsListItem from './HostMetricsListItem';
import HostMetricsDeleteButton from "./HostMetricsDeleteButton"; import HostMetricsDeleteButton from './HostMetricsDeleteButton';
const QS_CONFIG = getQSConfig('host_metrics', { const QS_CONFIG = getQSConfig('host_metrics', {
page: 1, page: 1,
page_size: 20, page_size: 20,
order_by: 'hostname', order_by: 'hostname',
deleted: false, deleted: false,
}); });
function HostMetrics() { function HostMetrics() {
@@ -34,15 +34,15 @@ function HostMetrics() {
error, error,
request: readHostMetrics, request: readHostMetrics,
} = useRequest( } = useRequest(
useCallback(async () => { useCallback(async () => {
const params = parseQueryString(QS_CONFIG, location.search); const params = parseQueryString(QS_CONFIG, location.search);
const list = await HostMetricsAPI.read(params); const list = await HostMetricsAPI.read(params);
return { return {
count: list.data.count, count: list.data.count,
results: list.data.results results: list.data.results,
}; };
}, [location]), }, [location]),
{ results: [], count: 0 } { results: [], count: 0 }
); );
useEffect(() => { useEffect(() => {
@@ -50,14 +50,11 @@ function HostMetrics() {
}, [readHostMetrics]); }, [readHostMetrics]);
const { selected, isAllSelected, handleSelect, selectAll, clearSelected } = const { selected, isAllSelected, handleSelect, selectAll, clearSelected } =
useSelected(results); useSelected(results);
return( return (
<> <>
<ScreenHeader <ScreenHeader streamType="none" breadcrumbConfig={breadcrumbConfig} />
streamType="none"
breadcrumbConfig={breadcrumbConfig}
/>
<PageSection> <PageSection>
<Card> <Card>
<PaginatedTable <PaginatedTable
@@ -66,19 +63,27 @@ function HostMetrics() {
items={results} items={results}
itemCount={count} itemCount={count}
pluralizedItemName={t`Host Metrics`} pluralizedItemName={t`Host Metrics`}
renderRow={(item, index)=> ( renderRow={(item, index) => (
<HostMetricsListItem <HostMetricsListItem
item={item} item={item}
isSelected={selected.some((row) => row.hostname === item.hostname)} isSelected={selected.some(
(row) => row.hostname === item.hostname
)}
onSelect={() => handleSelect(item)} onSelect={() => handleSelect(item)}
rowIndex={index} rowIndex={index}
/> />
)} )}
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
toolbarSearchColumns={[{name: t`Hostname`, key: 'hostname__icontains', isDefault: true}]} toolbarSearchColumns={[
{
name: t`Hostname`,
key: 'hostname__icontains',
isDefault: true,
},
]}
toolbarSearchableKeys={[]} toolbarSearchableKeys={[]}
toolbarRelatedSearchableKeys={[]} toolbarRelatedSearchableKeys={[]}
renderToolbar={(props) => renderToolbar={(props) => (
<DataListToolbar <DataListToolbar
{...props} {...props}
advancedSearchDisabled advancedSearchDisabled
@@ -89,46 +94,55 @@ function HostMetrics() {
<HostMetricsDeleteButton <HostMetricsDeleteButton
key="delete" key="delete"
onDelete={() => onDelete={() =>
Promise.all(selected.map((hostMetric) => Promise.all(
HostMetricsAPI.destroy(hostMetric.id))) selected.map((hostMetric) =>
.then(() => { readHostMetrics(); clearSelected(); }) HostMetricsAPI.destroy(hostMetric.id)
)
).then(() => {
readHostMetrics();
clearSelected();
})
} }
itemsToDelete={selected} itemsToDelete={selected}
pluralizedItemName={t`Host Metrics`} pluralizedItemName={t`Host Metrics`}
/>]} />,
/>} ]}
headerRow={ />
<HeaderRow qsConfig={QS_CONFIG}> )}
<HeaderCell headerRow={
sortKey="hostname"> <HeaderRow qsConfig={QS_CONFIG}>
{t`Hostname`} <HeaderCell sortKey="hostname">{t`Hostname`}</HeaderCell>
</HeaderCell> <HeaderCell
<HeaderCell sortKey="first_automation"
sortKey="first_automation" tooltip={t`When was the host first automated`}
tooltip={t`When was the host first automated`}> >
{t`First automated`} {t`First automated`}
</HeaderCell> </HeaderCell>
<HeaderCell <HeaderCell
sortKey="last_automation" sortKey="last_automation"
tooltip={t`When was the host last automated`}> tooltip={t`When was the host last automated`}
{t`Last automated`} >
</HeaderCell> {t`Last automated`}
<HeaderCell </HeaderCell>
sortKey="automated_counter" <HeaderCell
tooltip={t`How many times was the host automated`}> sortKey="automated_counter"
{t`Automation`} tooltip={t`How many times was the host automated`}
</HeaderCell> >
<HeaderCell {t`Automation`}
sortKey="used_in_inventories" </HeaderCell>
tooltip={t`How many inventories is the host in, recomputed on a weekly schedule`}> <HeaderCell
{t`Inventories`} sortKey="used_in_inventories"
</HeaderCell> tooltip={t`How many inventories is the host in, recomputed on a weekly schedule`}
<HeaderCell >
sortKey="deleted_counter" {t`Inventories`}
tooltip={t`How many times was the host deleted`}> </HeaderCell>
{t`Deleted`} <HeaderCell
</HeaderCell> sortKey="deleted_counter"
</HeaderRow> tooltip={t`How many times was the host deleted`}
>
{t`Deleted`}
</HeaderCell>
</HeaderRow>
} }
/> />
</Card> </Card>

View File

@@ -19,7 +19,7 @@ const mockHostMetrics = [
used_in_inventories: 1, used_in_inventories: 1,
deleted_counter: 1, deleted_counter: 1,
id: 1, id: 1,
} },
]; ];
function waitForLoaded(wrapper) { function waitForLoaded(wrapper) {

View File

@@ -1,18 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { import { func, node, string, arrayOf, shape } from 'prop-types';
func,
node,
string,
arrayOf,
shape,
} from 'prop-types';
import styled from 'styled-components'; import styled from 'styled-components';
import { import { Alert, Badge, Button, Tooltip } from '@patternfly/react-core';
Alert,
Badge,
Button,
Tooltip,
} from '@patternfly/react-core';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { getRelatedResourceDeleteCounts } from 'util/getRelatedResourceDeleteDetails'; import { getRelatedResourceDeleteCounts } from 'util/getRelatedResourceDeleteDetails';
import AlertModal from '../../components/AlertModal'; import AlertModal from '../../components/AlertModal';
@@ -82,8 +71,7 @@ function HostMetricsDeleteButton({
const modalTitle = t`Soft delete ${pluralizedItemName}?`; const modalTitle = t`Soft delete ${pluralizedItemName}?`;
const isDisabled = const isDisabled = itemsToDelete.length === 0;
itemsToDelete.length === 0;
const buildDeleteWarning = () => { const buildDeleteWarning = () => {
const deleteMessages = []; const deleteMessages = [];
@@ -92,7 +80,7 @@ function HostMetricsDeleteButton({
} }
if (deleteMessage) { if (deleteMessage) {
if (itemsToDelete.length > 1 || deleteDetails) { if (itemsToDelete.length > 1 || deleteDetails) {
deleteMessages.push(deleteMessage); deleteMessages.push(deleteMessage);
} }
} }
return ( return (
@@ -134,21 +122,21 @@ function HostMetricsDeleteButton({
return ( return (
<> <>
<Tooltip content={renderTooltip()} position="top"> <Tooltip content={renderTooltip()} position="top">
<div> <div>
<Button <Button
variant="secondary" variant="secondary"
isLoading={isLoading} isLoading={isLoading}
ouiaId="delete-button" ouiaId="delete-button"
spinnerAriaValueText={isLoading ? 'Loading' : undefined} spinnerAriaValueText={isLoading ? 'Loading' : undefined}
aria-label={t`Delete`} aria-label={t`Delete`}
onClick={() => toggleModal(true)} onClick={() => toggleModal(true)}
isDisabled={isDisabled} isDisabled={isDisabled}
> >
{t`Delete`} {t`Delete`}
</Button> </Button>
</div> </div>
</Tooltip> </Tooltip>
{isModalOpen && ( {isModalOpen && (
<AlertModal <AlertModal
variant="danger" variant="danger"
@@ -181,7 +169,10 @@ function HostMetricsDeleteButton({
> >
<div>{t`This action will soft delete the following:`}</div> <div>{t`This action will soft delete the following:`}</div>
{itemsToDelete.map((item) => ( {itemsToDelete.map((item) => (
<span key={item.hostname} id={`item-to-be-deleted-${item.hostname}`}> <span
key={item.hostname}
id={`item-to-be-deleted-${item.hostname}`}
>
<strong>{item.hostname}</strong> <strong>{item.hostname}</strong>
<br /> <br />
</span> </span>

View File

@@ -3,28 +3,34 @@ import React from 'react';
import { Tr, Td } from '@patternfly/react-table'; import { Tr, Td } from '@patternfly/react-table';
import { formatDateString } from 'util/dates'; import { formatDateString } from 'util/dates';
import { HostMetrics } from 'types'; import { HostMetrics } from 'types';
import {t} from "@lingui/macro"; import { t } from '@lingui/macro';
import {bool, func} from "prop-types"; import { bool, func } from 'prop-types';
function HostMetricsListItem({ item, isSelected, onSelect, rowIndex }) { function HostMetricsListItem({ item, isSelected, onSelect, rowIndex }) {
return ( return (
<Tr id={`host_metrics-row-${item.hostname}`} ouiaId={`host-metrics-row-${item.hostname}`}> <Tr
<Td select={{ rowIndex, isSelected, onSelect}} dataLabel={t`Selected`} /> id={`host_metrics-row-${item.hostname}`}
ouiaId={`host-metrics-row-${item.hostname}`}
>
<Td select={{ rowIndex, isSelected, onSelect }} dataLabel={t`Selected`} />
<Td dataLabel={t`Hostname`}>{item.hostname}</Td> <Td dataLabel={t`Hostname`}>{item.hostname}</Td>
<Td dataLabel={t`First automation`}>{formatDateString(item.first_automation)}</Td> <Td dataLabel={t`First automation`}>
<Td dataLabel={t`Last automation`}>{formatDateString(item.last_automation)}</Td> {formatDateString(item.first_automation)}
</Td>
<Td dataLabel={t`Last automation`}>
{formatDateString(item.last_automation)}
</Td>
<Td dataLabel={t`Automation`}>{item.automated_counter}</Td> <Td dataLabel={t`Automation`}>{item.automated_counter}</Td>
<Td dataLabel={t`Inventories`}>{item.used_in_inventories || 0}</Td> <Td dataLabel={t`Inventories`}>{item.used_in_inventories || 0}</Td>
<Td dataLabel={t`Deleted`}>{item.deleted_counter}</Td>< <Td dataLabel={t`Deleted`}>{item.deleted_counter}</Td>
/Tr> </Tr>
); );
} }
HostMetricsListItem.propTypes = { HostMetricsListItem.propTypes = {
item: HostMetrics.isRequired, item: HostMetrics.isRequired,
isSelected: bool.isRequired, isSelected: bool.isRequired,
onSelect: func.isRequired, onSelect: func.isRequired,
}; };
export default HostMetricsListItem; export default HostMetricsListItem;