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(RHINENG-9687): create system type filter #2190

Merged
merged 5 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions src/Utilities/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) => ({
Expand Down
14 changes: 14 additions & 0 deletions src/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const calculateSystemProfile = ({
rhcdFilter,
updateMethodFilter,
hostTypeFilter,
systemTypeFilter,
}) => {
let systemProfile = {};
const osFilterValues = Array.isArray(osFilter)
Expand Down Expand Up @@ -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,
});
Expand All @@ -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(
Expand Down
35 changes: 35 additions & 0 deletions src/components/InventoryTable/EntityTableToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
TEXT_FILTER,
TagsModal,
UPDATE_METHOD_KEY,
SYSTEM_TYPE_KEY,
arrayToSelection,
reduceFilters,
} from '../../Utilities/index';
Expand Down Expand Up @@ -60,6 +61,9 @@ import {
useTagsFilter,
useTextFilter,
useUpdateMethodFilter,
useSystemTypeFilter,
systemTypeFilterReducer,
systemTypeFilterState,
} from '../filters';
import useOperatingSystemFilter from '../filters/useOperatingSystemFilter';
import useFeatureFlag from '../../Utilities/useFeatureFlag';
Expand Down Expand Up @@ -93,6 +97,7 @@ const EntityTableToolbar = ({
onRefreshData,
loaded,
showTagModal,
showSystemTypeFilter,
showCentosVersions,
...props
}) => {
Expand All @@ -108,6 +113,7 @@ const EntityTableToolbar = ({
lastSeenFilterReducer,
updateMethodFilterReducer,
groupFilterReducer,
systemTypeFilterReducer,
]),
{
...textFilterState,
Expand All @@ -118,6 +124,7 @@ const EntityTableToolbar = ({
...updateMethodFilterState,
...lastSeenFilterState,
...groupFilterState,
...systemTypeFilterState,
}
);
const filters = useSelector(
Expand Down Expand Up @@ -185,6 +192,12 @@ const EntityTableToolbar = ({
reducer
);

const [
systemTypeConfig,
systemTypeChips,
systemTypeValue,
setSystemTypeValue,
] = useSystemTypeFilter(reducer);
/**
* Debounced function for fetching all tags.
*/
Expand Down Expand Up @@ -230,6 +243,9 @@ const EntityTableToolbar = ({
hostGroupFilter:
!(hideFilters.all && hideFilters.hostGroupFilter !== false) &&
!hideFilters.hostGroupFilter,
systemTypeFilter:
!(hideFilters.all && hideFilters.systemTypeFilter !== false) &&
!hideFilters.systemTypeFilter,
};

/**
Expand Down Expand Up @@ -282,6 +298,7 @@ const EntityTableToolbar = ({
lastSeenFilter,
updateMethodFilter,
hostGroupFilter,
systemTypeFilter,
} = reduceFilters([...(filters || []), ...(customFilters?.filters || [])]);

debouncedRefresh();
Expand All @@ -296,6 +313,7 @@ const EntityTableToolbar = ({
setUpdateMethodValue(updateMethodFilter);
enabledFilters.lastSeenFilter && setLastSeenFilterValue(lastSeenFilter);
enabledFilters.hostGroupFilter && setHostGroupValue(hostGroupFilter);
enabledFilters.systemTypeFilter && setHostGroupValue(systemTypeFilter);
}, []);

/**
Expand Down Expand Up @@ -402,6 +420,12 @@ const EntityTableToolbar = ({
}
}, [hostGroupValue]);

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

/**
* Mapper to simplify removing of any filter.
*/
Expand Down Expand Up @@ -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
Expand All @@ -451,6 +477,7 @@ const EntityTableToolbar = ({
enabledFilters.lastSeenFilter && setLastSeenFilterValue([]);
enabledFilters.updateMethodFilter && setUpdateMethodValue([]);
enabledFilters.hostGroupFilter && setHostGroupValue([]);
enabledFilters.systemTypeFilter && setSystemTypeValue([]);
setEndDate();
setStartDate(oldestDate);
dispatch(setFilter([]));
Expand All @@ -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) => {
Expand Down Expand Up @@ -503,6 +533,9 @@ const EntityTableToolbar = ({
...(enabledFilters.updateMethodFilter ? [updateMethodConfig] : []),
...(enabledFilters.lastSeenFilter ? [lastSeenFilter] : []),
...(enabledFilters.hostGroupFilter ? [hostGroupConfig] : []),
...(showSystemTypeFilter && enabledFilters.systemTypeFilter
? [systemTypeConfig]
: []),
...(showTags && enabledFilters.tags ? [tagsFilter] : []),
]
: []),
Expand Down Expand Up @@ -635,6 +668,7 @@ EntityTableToolbar.propTypes = {
lastSeen: PropTypes.bool,
updateMethodFilter: PropTypes.bool,
hostGroupFilter: PropTypes.bool,
systemTypeFilter: PropTypes.bool,
all: PropTypes.bool,
}),
paginationProps: PropTypes.object,
Expand All @@ -649,6 +683,7 @@ EntityTableToolbar.propTypes = {
disableDefaultColumns: PropTypes.any,
showCentosVersions: PropTypes.bool,
showNoGroupOption: PropTypes.bool,
showSystemTypeFilter: PropTypes.bool,
};

EntityTableToolbar.defaultProps = {
Expand Down
6 changes: 5 additions & 1 deletion src/components/InventoryTable/TitleColumn.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const TitleColumn = ({ children, id, item, ...props }) => (
<FontAwesomeImageIcon
fill="var(--pf-v5-global--icon--Color--light)"
margin="0px"
aria-label="Image mode icon"
/>
</Icon>
</Popover>
Expand All @@ -77,7 +78,10 @@ const TitleColumn = ({ children, id, item, ...props }) => (
}
>
<Icon style={{ marginRight: '8px' }}>
<BundleIcon color="var(--pf-v5-global--icon--Color--light)" />
<BundleIcon
color="var(--pf-v5-global--icon--Color--light)"
aria-label="Package mode icon"
/>
</Icon>
</Popover>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ exports[`TitleColumn should render correctly with NO data 1`] = `
>
<svg
aria-hidden="true"
aria-label="Package mode icon"
class="pf-v5-svg"
color="var(--pf-v5-global--icon--Color--light)"
fill="currentColor"
Expand Down Expand Up @@ -83,6 +84,7 @@ exports[`TitleColumn should render correctly with data 1`] = `
>
<svg
aria-hidden="true"
aria-label="Package mode icon"
class="pf-v5-svg"
color="var(--pf-v5-global--icon--Color--light)"
fill="currentColor"
Expand Down Expand Up @@ -131,6 +133,7 @@ exports[`TitleColumn should render correctly with href 1`] = `
>
<svg
aria-hidden="true"
aria-label="Package mode icon"
class="pf-v5-svg"
color="var(--pf-v5-global--icon--Color--light)"
fill="currentColor"
Expand Down Expand Up @@ -182,6 +185,7 @@ exports[`TitleColumn should render correctly with os_release 1`] = `
>
<svg
aria-hidden="true"
aria-label="Package mode icon"
class="pf-v5-svg"
color="var(--pf-v5-global--icon--Color--light)"
fill="currentColor"
Expand Down Expand Up @@ -230,6 +234,7 @@ exports[`TitleColumn should render correctly with to 1`] = `
>
<svg
aria-hidden="true"
aria-label="Package mode icon"
class="pf-v5-svg"
color="var(--pf-v5-global--icon--Color--light)"
fill="currentColor"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { Fragment, useEffect, useRef, useState } from 'react';
import React, {
Fragment,
useContext,
useEffect,
useRef,
useState,
} from 'react';
import PropTypes from 'prop-types';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import * as actions from '../../../store/actions';
Expand Down Expand Up @@ -26,6 +32,8 @@ import uniq from 'lodash/uniq';
import useTableActions from './useTableActions';
import useGlobalFilter from '../../filters/useGlobalFilter';
import useOnRefresh from '../../filters/useOnRefresh';
import useFeatureFlag from '../../../Utilities/useFeatureFlag';
import { AccountStatContext } from '../../../Routes';

const BulkDeleteButton = ({ selectedSystems, ...props }) => {
const requiredPermissions = selectedSystems.map(({ groups }) =>
Expand Down Expand Up @@ -63,6 +71,7 @@ const ConventionalSystemsTab = ({
initialLoading,
hasAccess,
hostGroupFilter,
systemTypeFilter,
}) => {
const chrome = useChrome();
const inventory = useRef(null);
Expand All @@ -78,7 +87,8 @@ const ConventionalSystemsTab = ({
rhcdFilter,
updateMethodFilter,
hostGroupFilter,
lastSeenFilter
lastSeenFilter,
systemTypeFilter
)
);
const [ediOpen, onEditOpen] = useState(false);
Expand Down Expand Up @@ -156,9 +166,12 @@ const ConventionalSystemsTab = ({
setAddHostGroupModalOpen
);

const isBootcEnabled = useFeatureFlag('hbi.ui.bifrost');
const { hasBootcImages } = useContext(AccountStatContext);
return (
<Fragment>
<InventoryTableCmp
showSystemTypeFilter={isBootcEnabled && hasBootcImages}
hasAccess={hasAccess}
isRbacEnabled
customFilters={{ filters, globalFilter }}
Expand Down Expand Up @@ -362,6 +375,10 @@ ConventionalSystemsTab.propTypes = {
PropTypes.arrayOf(PropTypes.string),
PropTypes.string,
]),
systemTypeFilter: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string),
PropTypes.string,
]),
};

ConventionalSystemsTab.defaultProps = {
Expand Down
1 change: 1 addition & 0 deletions src/components/filters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from './useRhcdFilter';
export * from './useUpdateMethodFilter';
export * from './useLastSeenFilter';
export * from './useGroupFilter';
export * from './useSystemTypeFilter';
export const filtersReducer = (reducersList) => (state, action) =>
reducersList.reduce(
(acc, curr) => ({
Expand Down
51 changes: 51 additions & 0 deletions src/components/filters/useSystemTypeFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useState } from 'react';
import {
SYSTEM_TYPE_KEY,
systemTypeOptions as defaultSystemTypeOptions,
} from '../../Utilities/index';

export const systemTypeFilterState = { systemTypeFilter: [] };
export const SYSTEM_TYPE_FILTER = 'SYSTEM_TYPE_FILTER';
export const systemTypeFilterReducer = (_state, { type, payload }) => ({
...(type === SYSTEM_TYPE_FILTER && {
systemTypeFilter: payload,
}),
});

export const useSystemTypeFilter = (
[state, dispatch] = [systemTypeFilterState]
) => {
let [filterStateValue, setStateValue] = useState([]);
const systemTypeValue = dispatch ? state.systemTypeFilter : filterStateValue;
const setValue = dispatch
? (newValue) => dispatch({ type: SYSTEM_TYPE_FILTER, payload: newValue })
: setStateValue;

const filter = {
label: 'System type',
value: 'not_nil',
type: 'checkbox',
filterValues: {
value: systemTypeValue,
onChange: (_e, value) => {
setValue(value);
},
items: defaultSystemTypeOptions,
},
};

const chip =
systemTypeValue?.length > 0
? [
{
category: 'System type',
type: SYSTEM_TYPE_KEY,
chips: defaultSystemTypeOptions
.filter(({ value }) => systemTypeValue.includes(value))
.map(({ label, ...props }) => ({ name: label, ...props })),
},
]
: [];

return [filter, chip, systemTypeValue, setValue];
};