Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import FormSelect from '../../../form/FormSelect';
import { getArtifactLabel, getFullArtifactURI } from '../../utils';
import LearnMoreLink from '../../../common/LearnMoreLink';
import { useAppLinks } from '../../../../hooks/useAppLinks';
import { FilterSearchParams } from '../../../../utils/status/devices';

export const isSelectTargetStepValid = (errors: FormikErrors<InstallAppFormik>) => {
return !errors.device && !errors.fleet;
Expand All @@ -51,13 +50,7 @@ const DeviceTarget = () => {
isLoading: devicesLoading,
isUpdating: devicesUpdating,
pagination: devicePagination,
} = useDevicesPaginated({
textFilters: {
[FilterSearchParams.NameOrAlias]: deviceNameFilter,
},
onlyDecommissioned: false,
onlyFleetless: true,
});
} = useDevicesPaginated(deviceNameFilter);

const handleDeviceSelect = React.useCallback(
async (device: Device) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,7 @@ const SpecificationsStep = ({ catalogItem, showNewDevice }: SpecificationsStepPr
const newDeviceRadioRef = React.useRef<HTMLSpanElement>(null);

const { fleets, isLoading: fleetsLoading } = useFleets({});
const { devices, isLoading: devicesLoading } = useDevicesPaginated({
onlyDecommissioned: false,
onlyFleetless: true,
});
const { devices, isLoading: devicesLoading } = useDevicesPaginated();

const unmanagedFleetsCount = fleets.filter((f) => !f.metadata?.owner).length;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { DeviceList } from '@flightctl/types';
import ListPage from '../../ListPage/ListPage';
import ListPageBody from '../../ListPage/ListPageBody';
import { useTranslation } from '../../../hooks/useTranslation';
import { useTablePagination } from '../../../hooks/useTablePagination';
import { useResetPaginationOnFilterChange, useTablePagination } from '../../../hooks/useTablePagination';
import { useDevices } from './useDevices';
import { useDeviceBackendFilters } from './useDeviceBackendFilters';

Expand All @@ -20,6 +20,7 @@ const DevicesPage = ({ canListER }: { canListER: boolean }) => {
const { t } = useTranslation();

const {
filterKey,
textFilters,
clearTextFilters,
setTextFilter,
Expand All @@ -37,6 +38,8 @@ const DevicesPage = ({ canListER }: { canListER: boolean }) => {

const { currentPage, setCurrentPage, onPageFetched, nextContinue, itemCount } = useTablePagination<DeviceList>();

useResetPaginationOnFilterChange(`${filterKey}|${onlyDecommissioned}`, setCurrentPage);

const {
devices: data,
isLoading: loading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ const validAppStatuses = Object.values(ApplicationsSummaryStatusType) as string[
const validUpdatedStatuses = Object.values(DeviceUpdatedStatusType) as string[];
const validDeviceStatuses = Object.values(DeviceSummaryStatusType) as string[];

const getSearchParamsQueryKey = (searchParams: URLSearchParams): string => {
return (
[...searchParams.entries()]
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.sort()
.join('&') || ''
);
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const getNewParams = (currentParams: URLSearchParams, newValues: { [key: string]: string[] }) => {
let newParams = [...currentParams.entries()];
const keys = Object.keys(newValues);
Expand Down Expand Up @@ -156,7 +165,10 @@ export const useDeviceBackendFilters = () => {
Object.values(activeStatuses).some((s) => !!s.length) ||
DEVICE_TEXT_FILTER_KEYS.some((key) => !!textFilters[key]);

const filterKey = React.useMemo(() => getSearchParamsQueryKey(searchParams), [searchParams]);

return {
filterKey,
textFilters,
setTextFilter,
clearTextFilters,
Expand Down
29 changes: 20 additions & 9 deletions libs/ui-components/src/components/Device/DevicesPage/useDevices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { useFetchPeriodically } from '../../../hooks/useFetchPeriodically';
import { FlightCtlLabel } from '../../../types/extraTypes';
import { FilterStatusMap } from './types';
import { PAGE_SIZE } from '../../../constants';
import { PaginationDetails, useTablePagination } from '../../../hooks/useTablePagination';
import {
PaginationDetails,
useResetPaginationOnFilterChange,
useTablePagination,
} from '../../../hooks/useTablePagination';

type DevicesEndpointArgs = {
/** Free-text filters synced with URL (name/alias, CVE ID, …). */
Expand Down Expand Up @@ -164,17 +168,24 @@ export type DevicesPaginatedResult = {

/**
* Hook for fetching devices with built-in pagination support.
* Use this for paginated tables/modals.

* Use this for paginated tables/modals of enrolled, fleetless devices.
*/
export const useDevicesPaginated = (args: {
textFilters?: Partial<Record<DeviceTextFilterKey, string>>;
ownerFleets?: string[];
onlyDecommissioned: boolean;
onlyFleetless?: boolean;
}): DevicesPaginatedResult => {
export const useDevicesPaginated = (deviceNameFilter?: string): DevicesPaginatedResult => {
const pagination = useTablePagination<DeviceList>();

useResetPaginationOnFilterChange(deviceNameFilter || '', pagination.setCurrentPage);

const textFilters = deviceNameFilter
? {
[FilterSearchParams.NameOrAlias]: deviceNameFilter,
}
: undefined;

const [devicesEndpoint, devicesDebouncing] = useDevicesEndpoint({
...args,
textFilters,
onlyDecommissioned: false,
onlyFleetless: true,
nextContinue: pagination.nextContinue,
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Expand Down
10 changes: 10 additions & 0 deletions libs/ui-components/src/hooks/useTablePagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,13 @@ export const useTablePagination = <T extends ApiList>(): PaginationDetails<T> =>

return { onPageFetched, currentPage, setCurrentPage, nextContinue, itemCount };
};

export const useResetPaginationOnFilterChange = (queryKey: string, setCurrentPage: (page: number) => void) => {
const prevQueryKeyRef = React.useRef(queryKey);
React.useEffect(() => {
if (prevQueryKeyRef.current !== queryKey) {
prevQueryKeyRef.current = queryKey;
setCurrentPage(1);
}
}, [queryKey, setCurrentPage]);
};
Loading