Add tooltips to inventory sync status

Add tooltips to inventory sync status on Inventory List.

See: https://github.com/ansible/awx/issues/7676
This commit is contained in:
nixocio 2021-01-25 16:50:26 -05:00
parent 9f691a048d
commit 287d181af7
3 changed files with 92 additions and 48 deletions

View File

@ -1,7 +1,7 @@
import 'styled-components/macro';
import React from 'react';
import { oneOf } from 'prop-types';
import { Label } from '@patternfly/react-core';
import { Label, Tooltip } from '@patternfly/react-core';
import {
CheckCircleIcon,
ExclamationCircleIcon,
@ -48,15 +48,19 @@ const icons = {
canceled: ExclamationTriangleIcon,
};
export default function StatusLabel({ status }) {
export default function StatusLabel({ status, tooltipContent = '' }) {
const label = status.charAt(0).toUpperCase() + status.slice(1);
const color = colors[status] || 'grey';
const Icon = icons[status];
return (
<Label variant="outline" color={color} icon={Icon ? <Icon /> : null}>
{label}
</Label>
<>
<Tooltip content={tooltipContent} position="top">
<Label variant="outline" color={color} icon={Icon ? <Icon /> : null}>
{label}
</Label>
</Tooltip>
</>
);
}

View File

@ -55,6 +55,19 @@ function InventoryListItem({
inventory.inventory_sources_with_failures > 0 ? 'error' : 'success';
}
let tooltipContent = '';
if (inventory.has_inventory_sources) {
if (inventory.inventory_sources_with_failures > 0) {
tooltipContent = i18n._(
t`${inventory.inventory_sources_with_failures} sources with sync failures.`
);
} else {
tooltipContent = i18n._(t`No inventory sync failures.`);
}
} else {
tooltipContent = i18n._(t`Not configured for inventory sync.`);
}
return (
<Tr id={inventory.id} aria-labelledby={labelId}>
<Td
@ -75,7 +88,9 @@ function InventoryListItem({
)}
</Td>
<Td dataLabel={i18n._(t`Status`)}>
{inventory.kind !== 'smart' && <StatusLabel status={syncStatus} />}
{inventory.kind !== 'smart' && (
<StatusLabel status={syncStatus} tooltipContent={tooltipContent} />
)}
</Td>
<Td dataLabel={i18n._(t`Type`)}>
{inventory.kind === 'smart'

View File

@ -7,24 +7,33 @@ import InventoryListItem from './InventoryListItem';
jest.mock('../../../api/models/Inventories');
describe('<InventoryListItem />', () => {
test('initially renders succesfully', () => {
const inventory = {
id: 1,
name: 'Inventory',
kind: '',
has_active_failures: true,
total_hosts: 10,
hosts_with_active_failures: 4,
has_inventory_sources: true,
total_inventory_sources: 4,
inventory_sources_with_failures: 5,
summary_fields: {
organization: {
id: 1,
name: 'Default',
},
user_capabilities: {
edit: true,
},
},
};
test('initially renders successfully', () => {
mountWithContexts(
<table>
<tbody>
<InventoryListItem
inventory={{
id: 1,
name: 'Inventory',
summary_fields: {
organization: {
id: 1,
name: 'Default',
},
user_capabilities: {
edit: true,
},
},
}}
inventory={inventory}
detailUrl="/inventories/inventory/1"
isSelected
onSelect={() => {}}
@ -34,25 +43,50 @@ describe('<InventoryListItem />', () => {
);
});
test('should render not configured tooltip', () => {
const wrapper = mountWithContexts(
<table>
<tbody>
<InventoryListItem
inventory={{ ...inventory, has_inventory_sources: false }}
detailUrl="/inventories/inventory/1"
isSelected
onSelect={() => {}}
/>
</tbody>
</table>
);
expect(wrapper.find('StatusLabel').prop('tooltipContent')).toBe(
'Not configured for inventory sync.'
);
});
test('should render success tooltip', () => {
const wrapper = mountWithContexts(
<table>
<tbody>
<InventoryListItem
inventory={{ ...inventory, inventory_sources_with_failures: 0 }}
detailUrl="/inventories/inventory/1"
isSelected
onSelect={() => {}}
/>
</tbody>
</table>
);
expect(wrapper.find('StatusLabel').prop('tooltipContent')).toBe(
'No inventory sync failures.'
);
});
test('should render prompt list item data', () => {
const wrapper = mountWithContexts(
<table>
<tbody>
<InventoryListItem
inventory={{
id: 1,
name: 'Inventory',
kind: '',
summary_fields: {
organization: {
id: 1,
name: 'Default',
},
user_capabilities: {
edit: true,
},
},
}}
inventory={inventory}
detailUrl="/inventories/inventory/1"
isSelected
onSelect={() => {}}
@ -61,6 +95,9 @@ describe('<InventoryListItem />', () => {
</table>
);
expect(wrapper.find('StatusLabel').length).toBe(1);
expect(wrapper.find('StatusLabel').prop('tooltipContent')).toBe(
`${inventory.inventory_sources_with_failures} sources with sync failures.`
);
expect(
wrapper
.find('Td')
@ -72,7 +109,7 @@ describe('<InventoryListItem />', () => {
.find('Td')
.at(2)
.text()
).toBe('Disabled');
).toBe('Error');
expect(
wrapper
.find('Td')
@ -92,19 +129,7 @@ describe('<InventoryListItem />', () => {
<table>
<tbody>
<InventoryListItem
inventory={{
id: 1,
name: 'Inventory',
summary_fields: {
organization: {
id: 1,
name: 'Default',
},
user_capabilities: {
edit: true,
},
},
}}
inventory={inventory}
detailUrl="/inventories/inventory/1"
isSelected
onSelect={() => {}}