diff --git a/src/Utilities/constants.js b/src/Utilities/constants.js index 90ad1685b..2c02ced50 100644 --- a/src/Utilities/constants.js +++ b/src/Utilities/constants.js @@ -8,6 +8,7 @@ export const REGISTERED_CHIP = 'registered_with'; export const OS_CHIP = 'operating_system'; export const RHCD_FILTER_KEY = 'rhc_client_id'; export const UPDATE_METHOD_KEY = 'system_update_method'; +export const SYSTEM_TYPE_KEY = 'system_type'; export const LAST_SEEN_CHIP = 'last_seen'; export const HOST_GROUP_CHIP = 'group_name'; // use the same naming as for the back end parameter //REPORTERS @@ -104,6 +105,17 @@ const initUpdateMethodOptions = [ export const updateMethodOptions = initUpdateMethodOptions; +export const systemTypeOptions = [ + { + label: 'Package mode', + value: 'nil', + }, + { + label: 'Image mode', + value: 'not_nil', + }, +]; + export function filterToGroup(filter = [], valuesKey = 'values') { return filter.reduce( (accGroup, group) => ({ diff --git a/src/api/api.js b/src/api/api.js index 746be097b..ef3ce740e 100644 --- a/src/api/api.js +++ b/src/api/api.js @@ -110,6 +110,7 @@ export const calculateSystemProfile = ({ rhcdFilter, updateMethodFilter, hostTypeFilter, + systemTypeFilter, }) => { let systemProfile = {}; const osFilterValues = Array.isArray(osFilter) @@ -166,6 +167,16 @@ export const calculateSystemProfile = ({ systemProfile['host_type'] = 'nil'; } + if (systemTypeFilter?.length) { + systemProfile.bootc_status = { + booted: { + image_digest: { + is: systemTypeFilter, + }, + }, + }; + } + return generateFilter({ system_profile: systemProfile, }); @@ -189,6 +200,9 @@ export const filtersReducer = (acc, filter = {}) => ({ ...('hostGroupFilter' in filter && { hostGroupFilter: filter.hostGroupFilter, }), + ...('systemTypeFilter' in filter && { + systemTypeFilter: filter.systemTypeFilter, + }), }); export async function getEntities( diff --git a/src/components/InventoryTable/EntityTableToolbar.js b/src/components/InventoryTable/EntityTableToolbar.js index 9deecc048..af26ffe8c 100644 --- a/src/components/InventoryTable/EntityTableToolbar.js +++ b/src/components/InventoryTable/EntityTableToolbar.js @@ -32,6 +32,7 @@ import { TEXT_FILTER, TagsModal, UPDATE_METHOD_KEY, + SYSTEM_TYPE_KEY, arrayToSelection, reduceFilters, } from '../../Utilities/index'; @@ -60,6 +61,9 @@ import { useTagsFilter, useTextFilter, useUpdateMethodFilter, + useSystemTypeFilter, + systemTypeFilterReducer, + systemTypeFilterState, } from '../filters'; import useOperatingSystemFilter from '../filters/useOperatingSystemFilter'; import useFeatureFlag from '../../Utilities/useFeatureFlag'; @@ -93,6 +97,7 @@ const EntityTableToolbar = ({ onRefreshData, loaded, showTagModal, + showSystemTypeFilter, showCentosVersions, ...props }) => { @@ -108,6 +113,7 @@ const EntityTableToolbar = ({ lastSeenFilterReducer, updateMethodFilterReducer, groupFilterReducer, + systemTypeFilterReducer, ]), { ...textFilterState, @@ -118,6 +124,7 @@ const EntityTableToolbar = ({ ...updateMethodFilterState, ...lastSeenFilterState, ...groupFilterState, + ...systemTypeFilterState, } ); const filters = useSelector( @@ -185,6 +192,12 @@ const EntityTableToolbar = ({ reducer ); + const [ + systemTypeConfig, + systemTypeChips, + systemTypeValue, + setSystemTypeValue, + ] = useSystemTypeFilter(reducer); /** * Debounced function for fetching all tags. */ @@ -230,6 +243,9 @@ const EntityTableToolbar = ({ hostGroupFilter: !(hideFilters.all && hideFilters.hostGroupFilter !== false) && !hideFilters.hostGroupFilter, + systemTypeFilter: + !(hideFilters.all && hideFilters.systemTypeFilter !== false) && + !hideFilters.systemTypeFilter, }; /** @@ -282,6 +298,7 @@ const EntityTableToolbar = ({ lastSeenFilter, updateMethodFilter, hostGroupFilter, + systemTypeFilter, } = reduceFilters([...(filters || []), ...(customFilters?.filters || [])]); debouncedRefresh(); @@ -296,6 +313,7 @@ const EntityTableToolbar = ({ setUpdateMethodValue(updateMethodFilter); enabledFilters.lastSeenFilter && setLastSeenFilterValue(lastSeenFilter); enabledFilters.hostGroupFilter && setHostGroupValue(hostGroupFilter); + enabledFilters.systemTypeFilter && setHostGroupValue(systemTypeFilter); }, []); /** @@ -402,6 +420,12 @@ const EntityTableToolbar = ({ } }, [hostGroupValue]); + useEffect(() => { + if (shouldReload && enabledFilters.systemTypeFilter) { + onSetFilter(systemTypeValue, 'systemTypeFilter', debouncedRefresh); + } + }, [systemTypeValue]); + /** * Mapper to simplify removing of any filter. */ @@ -437,6 +461,8 @@ const EntityTableToolbar = ({ setUpdateMethodValue(onDeleteFilter(deleted, updateMethodValue)), [HOST_GROUP_CHIP]: (deleted) => setHostGroupValue(onDeleteFilter(deleted, hostGroupValue)), + [SYSTEM_TYPE_KEY]: (deleted) => + setSystemTypeValue(onDeleteFilter(deleted, systemTypeValue)), }; /** * Function to reset all filters with 'Reset Filter' is clicked @@ -451,6 +477,7 @@ const EntityTableToolbar = ({ enabledFilters.lastSeenFilter && setLastSeenFilterValue([]); enabledFilters.updateMethodFilter && setUpdateMethodValue([]); enabledFilters.hostGroupFilter && setHostGroupValue([]); + enabledFilters.systemTypeFilter && setSystemTypeValue([]); setEndDate(); setStartDate(oldestDate); dispatch(setFilter([])); @@ -475,6 +502,9 @@ const EntityTableToolbar = ({ : []), ...(!hasItems && enabledFilters.lastSeenFilter ? lastSeenChip : []), ...(!hasItems && enabledFilters.hostGroupFilter ? hostGroupChips : []), + ...(showSystemTypeFilter && !hasItems && enabledFilters.systemTypeFilter + ? systemTypeChips + : []), ...(activeFiltersConfig?.filters || []), ], onDelete: (e, [deleted, ...restDeleted], isAll) => { @@ -503,6 +533,9 @@ const EntityTableToolbar = ({ ...(enabledFilters.updateMethodFilter ? [updateMethodConfig] : []), ...(enabledFilters.lastSeenFilter ? [lastSeenFilter] : []), ...(enabledFilters.hostGroupFilter ? [hostGroupConfig] : []), + ...(showSystemTypeFilter && enabledFilters.systemTypeFilter + ? [systemTypeConfig] + : []), ...(showTags && enabledFilters.tags ? [tagsFilter] : []), ] : []), @@ -635,6 +668,7 @@ EntityTableToolbar.propTypes = { lastSeen: PropTypes.bool, updateMethodFilter: PropTypes.bool, hostGroupFilter: PropTypes.bool, + systemTypeFilter: PropTypes.bool, all: PropTypes.bool, }), paginationProps: PropTypes.object, @@ -649,6 +683,7 @@ EntityTableToolbar.propTypes = { disableDefaultColumns: PropTypes.any, showCentosVersions: PropTypes.bool, showNoGroupOption: PropTypes.bool, + showSystemTypeFilter: PropTypes.bool, }; EntityTableToolbar.defaultProps = { diff --git a/src/components/InventoryTable/TitleColumn.js b/src/components/InventoryTable/TitleColumn.js index 4ab28e5ac..b32c800ed 100644 --- a/src/components/InventoryTable/TitleColumn.js +++ b/src/components/InventoryTable/TitleColumn.js @@ -60,6 +60,7 @@ const TitleColumn = ({ children, id, item, ...props }) => ( @@ -77,7 +78,10 @@ const TitleColumn = ({ children, id, item, ...props }) => ( } > - + )} diff --git a/src/components/InventoryTable/__snapshots__/TitleColumn.test.js.snap b/src/components/InventoryTable/__snapshots__/TitleColumn.test.js.snap index c38f75658..de68377e5 100644 --- a/src/components/InventoryTable/__snapshots__/TitleColumn.test.js.snap +++ b/src/components/InventoryTable/__snapshots__/TitleColumn.test.js.snap @@ -38,6 +38,7 @@ exports[`TitleColumn should render correctly with NO data 1`] = ` >