Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ESSNTL-4195): Inv table group filter #1776

Merged
merged 18 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/Utilities/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const OS_CHIP = 'operating_system';
export const RHCD_FILTER_KEY = 'rhc_client_id';
export const UPDATE_METHOD_KEY = 'system_update_method';
export const LAST_SEEN_CHIP = 'last_seen';
export const HOST_GROUP_CHIP = 'host_group';

export function subtractDate(days) {
const date = new Date();
Expand Down Expand Up @@ -141,8 +142,16 @@ export const reloadWrapper = (event, callback) => {

export const isEmpty = (check) => !check || check?.length === 0;

export const generateFilter = (status, source, tagsFilter, filterbyName,
operatingSystem, rhcdFilter, lastSeenFilter, updateMethodFilter) => ([
export const generateFilter = (status,
source,
tagsFilter,
filterbyName,
operatingSystem,
rhcdFilter,
updateMethodFilter,
hostGroup,
lastSeenFilter
) => ([
!isEmpty(status) && {
staleFilter: Array.isArray(status) ? status : [status]
},
Expand Down Expand Up @@ -173,6 +182,9 @@ export const generateFilter = (status, source, tagsFilter, filterbyName,
},
!isEmpty(updateMethodFilter) && {
updateMethodFilter: Array.isArray(updateMethodFilter) ? updateMethodFilter : [updateMethodFilter]
},
!isEmpty(hostGroup) && {
hostGroupFilter: Array.isArray(hostGroup) ? hostGroup : [hostGroup]
}
].filter(Boolean));

Expand Down
3 changes: 2 additions & 1 deletion src/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ export const filtersReducer = (acc, filter = {}) => ({
...'osFilter' in filter && { osFilter: filter.osFilter },
...'rhcdFilter' in filter && { rhcdFilter: filter.rhcdFilter },
...'lastSeenFilter' in filter && { lastSeenFilter: filter.lastSeenFilter },
...'updateMethodFilter' in filter && { updateMethodFilter: filter.updateMethodFilter }
...'updateMethodFilter' in filter && { updateMethodFilter: filter.updateMethodFilter },
...'groupHostFilter' in filter && { groupHostFilter: filter.groupHostFilter }
});

export async function getEntities(items, {
Expand Down
8 changes: 8 additions & 0 deletions src/components/GroupSystems/GroupSystems.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import {
featureFlagsInterceptors,
groupsInterceptors,
hostsInterceptors,
systemProfileInterceptors
} from '../../../cypress/support/interceptors';
Expand Down Expand Up @@ -76,6 +77,7 @@ describe('renders correctly', () => {
hostsInterceptors.successful();
featureFlagsInterceptors.successful();
systemProfileInterceptors['operating system, successful empty']();
groupsInterceptors['successful with some items']();
mountTable();

cy.wait('@getHosts');
Expand All @@ -99,6 +101,7 @@ describe('defaults', () => {
hostsInterceptors.successful();
featureFlagsInterceptors.successful();
systemProfileInterceptors['operating system, successful empty']();
groupsInterceptors['successful with some items']();
mountTable();

cy.wait('@getHosts');
Expand All @@ -121,6 +124,7 @@ describe('pagination', () => {
hostsInterceptors.successful();
featureFlagsInterceptors.successful();
systemProfileInterceptors['operating system, successful empty']();
groupsInterceptors['successful with some items']();
mountTable();

cy.wait('@getHosts');
Expand Down Expand Up @@ -155,6 +159,7 @@ describe('sorting', () => {
hostsInterceptors.successful();
featureFlagsInterceptors.successful();
systemProfileInterceptors['operating system, successful empty']();
groupsInterceptors['successful with some items']();
mountTable();

cy.wait('@getHosts');
Expand Down Expand Up @@ -194,6 +199,7 @@ describe('filtering', () => {
hostsInterceptors.successful();
featureFlagsInterceptors.successful();
systemProfileInterceptors['operating system, successful empty']();
groupsInterceptors['successful with some items']();
mountTable();

cy.wait('@getHosts');
Expand Down Expand Up @@ -243,6 +249,7 @@ describe('selection and bulk selection', () => {
hostsInterceptors.successful();
featureFlagsInterceptors.successful();
systemProfileInterceptors['operating system, successful empty']();
groupsInterceptors['successful with some items']();
mountTable();

cy.wait('@getHosts');
Expand Down Expand Up @@ -301,6 +308,7 @@ describe('edge cases', () => {
hostsInterceptors['successful empty']();
featureFlagsInterceptors.successful();
systemProfileInterceptors['operating system, successful empty']();
groupsInterceptors['successful with some items']();
mountTable();

cy.wait('@getHosts');
Expand Down
47 changes: 38 additions & 9 deletions src/components/InventoryTable/EntityTableToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
arrayToSelection,
RHCD_FILTER_KEY,
UPDATE_METHOD_KEY,
LAST_SEEN_CHIP
LAST_SEEN_CHIP,
HOST_GROUP_CHIP
} from '../../Utilities/index';
import { onDeleteFilter, onDeleteTag } from './helpers';
import {
Expand All @@ -44,10 +45,13 @@ import {
updateMethodFilterReducer,
updateMethodFilterState,
lastSeenFilterReducer,
lastSeenFilterState
lastSeenFilterState,
groupFilterReducer,
groupFilterState
} from '../filters';
import useOperatingSystemFilter from '../filters/useOperatingSystemFilter';
import useFeatureFlag from '../../Utilities/useFeatureFlag';
import useGroupFilter from '../filters/useGroupFilter';
import { DatePicker, Split, SplitItem } from '@patternfly/react-core';

/**
Expand Down Expand Up @@ -87,15 +91,17 @@ const EntityTableToolbar = ({
operatingSystemFilterReducer,
rhcdFilterReducer,
lastSeenFilterReducer,
updateMethodFilterReducer
updateMethodFilterReducer,
groupFilterReducer
]), {
...textFilterState,
...stalenessFilterState,
...registeredWithFilterState,
...tagsFilterState,
...rhcdFilterState,
...updateMethodFilterState,
...lastSeenFilterState
...lastSeenFilterState,
...groupFilterState
});
const filters = useSelector(({ entities: { activeFilters } }) => activeFilters);
const allTagsLoaded = useSelector(({ entities: { allTagsLoaded } }) => allTagsLoaded);
Expand All @@ -109,9 +115,10 @@ const EntityTableToolbar = ({
toValidator, onFromChange, onToChange, endDate, startDate, rangeValidator] = useLastSeenFilter(reducer);
const [osFilterConfig, osFilterChips, osFilterValue, setOsFilterValue] = useOperatingSystemFilter();
const [updateMethodConfig, updateMethodChips, updateMethodValue, setUpdateMethodValue] = useUpdateMethodFilter(reducer);
const [hostGroupConfig, hostGroupChips, hostGroupValue, setHostGroupValue] = useGroupFilter();

const isUpdateMethodEnabled = useFeatureFlag('hbi.ui.system-update-method');

const groupsEnabled = useFeatureFlag('hbi.ui.inventory-groups');
const {
tagsFilter,
tagsChip,
Expand All @@ -127,7 +134,7 @@ const EntityTableToolbar = ({
const debounceGetAllTags = useCallback(debounce((config, options) => {
if (showTags && !hasItems && hasAccess) {
dispatch(fetchAllTags(config, {
...options?.pagination
...options?.paginationhideFilters
}, getTags));
}
}, 800), [customFilters?.tags]);
Expand All @@ -143,7 +150,9 @@ const EntityTableToolbar = ({
//hides the filter untill API is ready. JIRA: RHIF-169
updateMethodFilter: isUpdateMethodEnabled &&
!(hideFilters.all && hideFilters.updateMethodFilter !== false)
&& !hideFilters.updateMethodFilter
&& !hideFilters.updateMethodFilter,
hostGroupFilter: groupsEnabled && !(hideFilters.all && hideFilters.hostGroupFilter !== false)
&& !hideFilters.hostGroupFilter
};

/**
Expand Down Expand Up @@ -181,7 +190,15 @@ const EntityTableToolbar = ({
*/
useEffect(() => {
const {
textFilter, tagFilters, staleFilter, registeredWithFilter, osFilter, rhcdFilter, lastSeenFilter, updateMethodFilter
textFilter,
tagFilters,
staleFilter,
registeredWithFilter,
osFilter,
rhcdFilter,
lastSeenFilter,
updateMethodFilter,
groupFilter
} = reduceFilters([...filters || [], ...customFilters?.filters || []]);

debouncedRefresh();
Expand All @@ -193,6 +210,7 @@ const EntityTableToolbar = ({
enabledFilters.rhcdFilter && setRhcdFilterValue(rhcdFilter);
enabledFilters.updateMethodFilter && setUpdateMethodValue(updateMethodFilter);
enabledFilters.lastSeenFilter && setLastSeenFilterValue(lastSeenFilter);
enabledFilters.hostGroupFilter && setHostGroupValue(groupFilter);
}, []);

/**
Expand Down Expand Up @@ -284,6 +302,12 @@ const EntityTableToolbar = ({
}
}, [updateMethodValue]);

useEffect(() => {
if (shouldReload && enabledFilters.hostGroupFilter) {
onSetFilter(hostGroupValue, 'hostGroupFilter', debouncedRefresh);
}
}, [hostGroupValue]);

/**
* Mapper to simplify removing of any filter.
*/
Expand All @@ -303,7 +327,8 @@ const EntityTableToolbar = ({
[OS_CHIP]: (deleted) => setOsFilterValue(xor(osFilterValue, deleted.chips.map(({ value }) => value))),
[RHCD_FILTER_KEY]: (deleted) => setRhcdFilterValue(onDeleteFilter(deleted, rhcdFilterValue)),
[LAST_SEEN_CHIP]: (deleted) => setLastSeenFilterValue(onDeleteFilter(deleted, [lastSeenFilterValue.mark])),
[UPDATE_METHOD_KEY]: (deleted) => setUpdateMethodValue(onDeleteFilter(deleted, updateMethodValue))
[UPDATE_METHOD_KEY]: (deleted) => setUpdateMethodValue(onDeleteFilter(deleted, updateMethodValue)),
[HOST_GROUP_CHIP]: (deleted) => setHostGroupValue(onDeleteFilter(deleted, hostGroupValue))
};
/**
* Function to reset all filters with 'Reset Filter' is clicked
Expand All @@ -317,6 +342,7 @@ const EntityTableToolbar = ({
enabledFilters.rhcdFilter && setRhcdFilterValue([]);
enabledFilters.lastSeenFilter && setLastSeenFilterValue([]);
enabledFilters.updateMethodFilter && setUpdateMethodValue([]);
enabledFilters.hostGroupFilter && setHostGroupValue([]);
dispatch(setFilter([]));
updateData({ page: 1, filters: [] });
};
Expand All @@ -336,6 +362,7 @@ const EntityTableToolbar = ({
...!hasItems && enabledFilters.rhcdFilter ? rhcdFilterChips : [],
...!hasItems && enabledFilters.updateMethodFilter ? updateMethodChips : [],
...!hasItems && enabledFilters.lastSeenFilter ? lastSeenChip : [],
...!hasItems && enabledFilters.hostGroupFilter ? hostGroupChips : [],
...activeFiltersConfig?.filters || []
],
onDelete: (e, [deleted, ...restDeleted], isAll) => {
Expand All @@ -362,6 +389,7 @@ const EntityTableToolbar = ({
...enabledFilters.rhcdFilter ? [rhcdFilterConfig] : [],
...enabledFilters.updateMethodFilter ? [updateMethodConfig] : [],
...enabledFilters.lastSeenFilter ? [lastSeenFilter] : [],
...enabledFilters.hostGroupFilter ? [hostGroupConfig] : [],
...showTags && enabledFilters.tags ? [tagsFilter] : []
] : [],
...filterConfig?.items || []
Expand Down Expand Up @@ -477,6 +505,7 @@ EntityTableToolbar.propTypes = {
rhcdFilter: PropTypes.bool,
lastSeen: PropTypes.bool,
updateMethodFilter: PropTypes.bool,
hostGroupFilter: PropTypes.bool,
all: PropTypes.bool
}),
paginationProps: PropTypes.object,
Expand Down
4 changes: 2 additions & 2 deletions src/components/InventoryTable/EntityTableToolbar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ describe('EntityTableToolbar', () => {
</Provider>);
wrapper.find('.ins-c-chip-filters button.pf-m-link').last().simulate('click');
const actions = store.getActions();
expect(actions.length).toBe(3);
expect(actions.length).toBe(4);
expect(actions[actions.length - 2]).toMatchObject({ type: 'CLEAR_FILTERS' });
expect(onRefreshData).toHaveBeenCalledWith({ filters: [], page: 1 });
});
Expand All @@ -355,7 +355,7 @@ describe('EntityTableToolbar', () => {

const wrapper = mount(<Provider store={store}>
<EntityTableToolbar
hideFilters={{ all: true, name: false }}
hideFilters={{ all: true, name: false, group: true }}
page={1}
total={500}
perPage={50}
Expand Down
9 changes: 8 additions & 1 deletion src/components/InventoryTable/InventoryTable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,14 @@ describe('InventoryTable', () => {
</Provider>);

expect(wrapper.find(ConditionalFilter).props().items.map(({ label }) => label)).toEqual(
['Status', 'Operating System', 'Data Collector', 'RHC status', 'System Update Method', 'Last seen', 'Tags']
['Status',
'Operating System',
'Data Collector',
'RHC status',
'System Update Method',
'Last seen',
'Group',
'Tags']
);
});

Expand Down
1 change: 1 addition & 0 deletions src/components/InventoryTable/hooks/useColumns.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const useColumns = (columnsProp, disableDefaultColumns, showTags, columnsCounter
)
);
const disabledColumns = Array.isArray(disableDefaultColumns) ? disableDefaultColumns : [];
//condition for the newDefaultColumns should be removed after inventory groups is released
const defaultColumnsFiltered = useMemo(() => (disableDefaultColumns === true) ?
[] : defaultColumns(groupsEnabled).filter(({ key }) =>
isColumnEnabled(key, disabledColumns, showTags)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`useGroupFilter with groups loaded should match snapshot 1`] = `
Array [
Object {
"filterValues": Object {
"items": Array [
Object {
"label": "nisi ut consequat ad",
"value": "nisi ut consequat ad",
},
Object {
"label": "nisi ut consequat ad1",
"value": "nisi ut consequat ad1",
},
Object {
"label": "nisi ut consequat ad2",
"value": "nisi ut consequat ad2",
},
],
"onChange": [Function],
"value": Array [],
},
"label": "Group",
"type": "checkbox",
"value": "group-host-filter",
},
Array [],
Array [],
[Function],
]
`;

exports[`useGroupFilter with groups loaded should return correct chips array, current value and value setter 1`] = `
Array [
Object {
"category": "Group",
"chips": Array [
Object {
"name": "nisi ut consequat ad1",
"value": "nisi ut consequat ad1",
},
],
"type": "host_group",
},
]
`;

exports[`useGroupFilter with groups loaded should return empty state value if no groups obtained 1`] = `
Array [
Object {
"filterValues": Object {
"items": Array [],
"onChange": [Function],
"value": Array [],
},
"label": "Group",
"type": "checkbox",
"value": "group-host-filter",
},
Array [],
Array [],
[Function],
]
`;

exports[`useGroupFilter with groups yet not loaded should return empty state value 1`] = `
Array [
Object {
"filterValues": Object {
"items": Array [],
"onChange": [Function],
"value": Array [],
},
"label": "Group",
"type": "checkbox",
"value": "group-host-filter",
},
Array [],
Array [],
[Function],
]
`;
Loading