diff --git a/src/inventoryPoc/FilterToolbar.tsx b/src/inventoryPoc/FilterToolbar.tsx new file mode 100644 index 000000000..234e79b6a --- /dev/null +++ b/src/inventoryPoc/FilterToolbar.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { HostApiOptions } from './api'; +import { Toolbar, ToolbarContent, ToolbarItem } from '@patternfly/react-core/dist/dynamic/components/Toolbar'; +import { Pagination } from '@patternfly/react-core'; + +export type FilterToolbarProps = HostApiOptions & { + onSetPage: (page: number) => void; + onPerPageSelect: (perPage: number) => void; +}; + +const FilterToolbar = (props: FilterToolbarProps) => { + const { page, perPage, onSetPage, onPerPageSelect } = props; + return ( + <> + + + + onPerPageSelect(newPerPage)} + onSetPage={(_e, newPage) => onSetPage(newPage)} + page={page} + perPage={perPage} + perPageOptions={[5, 10, 20, 50, 100].map((i) => ({ title: `${i}`, value: i }))} + /> + + + + + ); +}; + +export default FilterToolbar; diff --git a/src/inventoryPoc/InventoryColumn.ts b/src/inventoryPoc/InventoryColumn.ts index 163f54bf8..7a39b15dc 100644 --- a/src/inventoryPoc/InventoryColumn.ts +++ b/src/inventoryPoc/InventoryColumn.ts @@ -23,11 +23,13 @@ export class BaseInventoryColumn { private columnId: string; private title: ReactNode; private columnData: BaseColumnData; + private sortable?: boolean = false; - constructor(columnId: string, title: ReactNode, { columnData }: { columnData: BaseColumnData }) { + constructor(columnId: string, title: ReactNode, { columnData }: { columnData: BaseColumnData }, { sortable }: { sortable?: boolean } = {}) { this.columnId = columnId; this.title = title; this.columnData = columnData; + this.sortable = sortable; } getColumnId(): string { @@ -42,6 +44,10 @@ export class BaseInventoryColumn { return this.columnData; } + getSortable(): boolean { + return !!this.sortable; + } + setColumnData(columnData: BaseColumnData): void { this.columnData = columnData; } diff --git a/src/inventoryPoc/ModularInventory.tsx b/src/inventoryPoc/ModularInventory.tsx index 9413b2866..1884690f6 100644 --- a/src/inventoryPoc/ModularInventory.tsx +++ b/src/inventoryPoc/ModularInventory.tsx @@ -5,7 +5,7 @@ import { DateFormat } from '@redhat-cloud-services/frontend-components/DateForma import SecurityIcon from '@patternfly/react-icons/dist/dynamic/icons/security-icon'; import TagIcon from '@patternfly/react-icons/dist/dynamic/icons/tag-icon'; -import { AdvisorSystem, Host, getHostCVEs, getHostInsights, getHostPatch, getHostTags, getHosts } from './api'; +import { AdvisorSystem, Host, HostApiOptions, getHostCVEs, getHostInsights, getHostPatch, getHostTags, getHosts } from './api'; import { Checkbox } from '@patternfly/react-core/dist/dynamic/components/Checkbox'; import { Icon } from '@patternfly/react-core/dist/dynamic/components/Icon'; import { Skeleton } from '@patternfly/react-core/dist/dynamic/components/Skeleton'; @@ -13,6 +13,7 @@ import ShieldIcon from '@patternfly/react-icons/dist/dynamic/icons/shield-alt-ic import BugIcon from '@patternfly/react-icons/dist/dynamic/icons/bug-icon'; import CogIcon from '@patternfly/react-icons/dist/dynamic/icons/cog-icon'; import { Toolbar, ToolbarContent, ToolbarItem } from '@patternfly/react-core/dist/dynamic/components/Toolbar'; +import FilterToolbar from './FilterToolbar'; function createRows( columns: { @@ -110,14 +111,40 @@ function useColumnData(columns: InventoryColumn[]) { return res; } -const ModularInventory = ({ columns }: { columns: Omit[] }) => { +const ModularInventory = ({ + columns, + onSort, + sortBy, + sortDirection, +}: { + sortBy: number; + sortDirection: 'asc' | 'desc'; + onSort: (index: number, direction: 'asc' | 'desc') => void; + columns: Omit[]; +}) => { const [allData] = useColumnData(columns as InventoryColumn[]); return ( - {columns.map((column) => ( - + {columns.map((column, idx) => ( + ))} @@ -136,12 +163,12 @@ const ModularInventory = ({ columns }: { columns: Omit { - return new BaseInventoryColumn('id', 'System ID', { - columnData: hosts.map((host) => host.id), - }); + return new BaseInventoryColumn( + 'id', + 'System ID', + { + columnData: hosts.map((host) => host.id), + }, + { sortable: true } + ); }, - name: (hosts: Host[]) => { - return new BaseInventoryColumn('name', 'System Name', { - columnData: hosts.map((host) => ( - - {host.display_name} - - )), - }); + display_name: (hosts: Host[]) => { + return new BaseInventoryColumn( + 'display_name', + 'System Name', + { + columnData: hosts.map((host) => ( + + {host.display_name} + + )), + }, + { + sortable: true, + } + ); }, 'all-cves': (_e, cvePromises: ReturnType[]) => { @@ -363,14 +403,21 @@ const columnsRegistry: { }); }, - lastCheckIn: (hosts: Host[]) => { - return new BaseInventoryColumn('lastCheckIn', 'Last check-in', { - columnData: hosts.map((host) => - host.per_reporter_staleness.puptoo?.last_check_in ? ( - - ) : null - ), - }); + updated: (hosts: Host[]) => { + return new BaseInventoryColumn( + 'updated', + 'Last check-in', + { + columnData: hosts.map((host) => + host.per_reporter_staleness.puptoo?.last_check_in ? ( + + ) : null + ), + }, + { + sortable: true, + } + ); }, }; @@ -414,19 +461,40 @@ const ModularInventoryRoute = () => { }, [hosts, enabledColumns]); async function initData() { - const response = await getHosts(); + const response = await getHosts(filterState); setHosts(response.results); getHostTags(response.results[0].insights_id); } + const [filterState, setFilterState] = useState({ page: 1, perPage: 20, orderBy: 'updated', orderHow: 'DESC' }); useEffect(() => { initData(); - }, []); + }, [JSON.stringify(filterState)]); + + const onPerPageSelect = (perPage: number) => { + setFilterState((prev) => ({ ...prev, perPage })); + }; + const onSetPage = (page: number) => { + setFilterState((prev) => ({ ...prev, page })); + }; return (
- + + { + console.log(index, direction); + setFilterState((prev) => ({ + ...prev, + orderBy: (columnIds[index] as any) ?? 'updated', + orderHow: (direction.toUpperCase() as any) ?? 'DESC', + })); + }} + columns={cols} + />
); }; diff --git a/src/inventoryPoc/api.ts b/src/inventoryPoc/api.ts index ef7832d20..8608656bc 100644 --- a/src/inventoryPoc/api.ts +++ b/src/inventoryPoc/api.ts @@ -18,13 +18,15 @@ export type Host = { }; }; -export const getHosts = async () => { +export type HostApiOptions = { page?: number; perPage?: number; orderBy?: 'updated' | 'display_name' | 'id'; orderHow?: 'ASC' | 'DESC' }; + +export const getHosts = async ({ orderBy = 'updated', orderHow = 'DESC', page = 1, perPage = 20 }: HostApiOptions) => { const response = await axios.get<{ results: Host[] }>('/api/inventory/v1/hosts', { params: { - page: 1, - per_page: 20, - order_by: 'updated', - order_how: 'DESC', + page, + per_page: perPage, + order_by: orderBy, + order_how: orderHow, 'fields[system_profile]': ['operating_system'], }, });
{column.getTitle()} onSort(index, direction), + } + : undefined + } + key={column.getColumnId()} + > + {column.getTitle()} +