From 06aec6401f40b347825da7121f3e271dc0d4b5eb Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:35:55 -0400 Subject: [PATCH] Fleet UI: Manage queries page uses URL params as source of truth for table and inherited table views (#14750) --- changes/14733-14661-queries-page-fix | 1 + .../TableContainer/TableContainer.tsx | 1 + .../ManageQueriesPage/ManageQueriesPage.tsx | 5 +- .../components/QueriesTable/QueriesTable.tsx | 100 ++++++++++++------ 4 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 changes/14733-14661-queries-page-fix diff --git a/changes/14733-14661-queries-page-fix b/changes/14733-14661-queries-page-fix new file mode 100644 index 0000000000..afcbb9db80 --- /dev/null +++ b/changes/14733-14661-queries-page-fix @@ -0,0 +1 @@ +- Add inherited table information to URL params and use URL params for source of truth to fix any bugs between multi-table view diff --git a/frontend/components/TableContainer/TableContainer.tsx b/frontend/components/TableContainer/TableContainer.tsx index 257f9443c6..540578d8a4 100644 --- a/frontend/components/TableContainer/TableContainer.tsx +++ b/frontend/components/TableContainer/TableContainer.tsx @@ -84,6 +84,7 @@ interface ITableContainerProps { customControl?: () => JSX.Element; stackControls?: boolean; onSelectSingleRow?: (value: Row | IRowProps) => void; + /** Use for clientside filtering: Use key global for filtering on any column, or use column id as key */ filters?: Record; renderCount?: () => JSX.Element | null; renderFooter?: () => JSX.Element | null; diff --git a/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx b/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx index 73290cecab..a3319aac86 100644 --- a/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx +++ b/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx @@ -50,6 +50,9 @@ interface IManageQueriesPageProps { order_key?: string; order_direction?: "asc" | "desc"; team_id?: string; + inherited_order_key?: string; + inherited_order_direction?: "asc" | "desc"; + inherited_page?: string; }; search: string; }; @@ -76,7 +79,6 @@ const ManageQueriesPage = ({ location, }: IManageQueriesPageProps): JSX.Element => { const queryParams = location.query; - const { isGlobalAdmin, isTeamAdmin, @@ -93,7 +95,6 @@ const ManageQueriesPage = ({ const { setLastEditedQueryBody, setSelectedQueryTargetsByType } = useContext( QueryContext ); - const { setResetSelectedRows } = useContext(TableContext); const { renderFlash } = useContext(NotificationContext); diff --git a/frontend/pages/queries/ManageQueriesPage/components/QueriesTable/QueriesTable.tsx b/frontend/pages/queries/ManageQueriesPage/components/QueriesTable/QueriesTable.tsx index bf8f1271d0..40f11cf2ad 100644 --- a/frontend/pages/queries/ManageQueriesPage/components/QueriesTable/QueriesTable.tsx +++ b/frontend/pages/queries/ManageQueriesPage/components/QueriesTable/QueriesTable.tsx @@ -40,6 +40,9 @@ interface IQueriesTableProps { order_key?: string; order_direction?: "asc" | "desc"; team_id?: string; + inherited_order_key?: string; + inherited_order_direction?: "asc" | "desc"; + inherited_page?: string; }; isInherited?: boolean; } @@ -99,21 +102,37 @@ const QueriesTable = ({ // Functions to avoid race conditions const initialSearchQuery = (() => queryParams?.query ?? "")(); const initialSortHeader = (() => - (queryParams?.order_key as "name" | "updated_at" | "author") ?? "name")(); + (queryParams?.order_key as "name" | "updated_at" | "author") ?? + DEFAULT_SORT_HEADER)(); const initialSortDirection = (() => - (queryParams?.order_direction as "asc" | "desc") ?? "asc")(); + (queryParams?.order_direction as "asc" | "desc") ?? + DEFAULT_SORT_DIRECTION)(); const initialPlatform = (() => (queryParams?.platform as "all" | "windows" | "linux" | "darwin") ?? - "all")(); + DEFAULT_PLATFORM)(); const initialPage = (() => queryParams && queryParams.page ? parseInt(queryParams?.page, 10) : 0)(); + const initialInheritedSortHeader = (() => + (queryParams?.inherited_order_key as "name" | "failing_host_count") ?? + DEFAULT_SORT_HEADER)(); + const initialInheritedSortDirection = (() => + (queryParams?.inherited_order_direction as "asc" | "desc") ?? + DEFAULT_SORT_DIRECTION)(); + const initialInheritedPage = (() => + queryParams && queryParams.inherited_page + ? parseInt(queryParams?.inherited_page, 10) + : 0)(); // Never set as state as URL is source of truth const searchQuery = initialSearchQuery; const platform = initialPlatform; - const page = initialPage; - const sortDirection = initialSortDirection; - const sortHeader = initialSortHeader; + const page = isInherited ? initialInheritedPage : initialPage; + const sortDirection = isInherited + ? initialInheritedSortDirection + : initialSortDirection; + const sortHeader = isInherited + ? initialInheritedSortHeader + : initialSortHeader; // TODO: Look into useDebounceCallback with dependencies const onQueryChange = useCallback( @@ -128,27 +147,43 @@ const QueriesTable = ({ // Rebuild queryParams to dispatch new browser location to react-router const newQueryParams: { [key: string]: string | number | undefined } = {}; - if (!isEmpty(newSearchQuery)) { + // Updates main query table URL params + // No change to inherited query table URL params + if (!isInherited) { + newQueryParams.order_key = newSortHeader; + newQueryParams.order_direction = newSortDirection; + newQueryParams.platform = platform; // must set from URL + newQueryParams.page = newPageIndex; newQueryParams.query = newSearchQuery; + // Reset page number to 0 for new filters + if ( + newSortDirection !== sortDirection || + newSortHeader !== sortHeader || + newSearchQuery !== searchQuery + ) { + newQueryParams.page = "0"; + } } - newQueryParams.order_key = newSortHeader || DEFAULT_SORT_HEADER; - newQueryParams.order_direction = - newSortDirection || DEFAULT_SORT_DIRECTION; - newQueryParams.platform = platform || DEFAULT_PLATFORM; // must set from URL - newQueryParams.page = newPageIndex; - // Reset page number to 0 for new filters - if ( - newSortDirection !== sortDirection || - newSortHeader !== sortHeader || - newSearchQuery !== searchQuery - ) { - newQueryParams.page = 0; + // Updates inherited query table URL params + // No change to main query table URL params + if (isInherited) { + newQueryParams.inherited_order_key = newSortHeader; + newQueryParams.inherited_order_direction = newSortDirection; + newQueryParams.inherited_page = newPageIndex; + // Reset page number to 0 for new filters + if ( + newSortDirection !== initialInheritedSortDirection || + newSortHeader !== initialInheritedSortHeader + ) { + newQueryParams.inherited_page = "0"; + } } + newQueryParams.team_id = queryParams?.team_id; const locationPath = getNextLocationPath({ pathPrefix: PATHS.MANAGE_QUERIES, - queryParams: newQueryParams, + queryParams: { ...queryParams, ...newQueryParams }, }); router?.replace(locationPath); @@ -158,16 +193,21 @@ const QueriesTable = ({ const onClientSidePaginationChange = useCallback( (pageIndex: number) => { + const newQueryParams = isInherited + ? { + ...queryParams, + inherited_page: pageIndex, // update inherited page index + query: searchQuery, + } + : { + ...queryParams, + page: pageIndex, // update main table index + query: searchQuery, + }; + const locationPath = getNextLocationPath({ pathPrefix: PATHS.MANAGE_QUERIES, - queryParams: { - ...queryParams, - page: pageIndex, - platform, - query: searchQuery, - order_direction: sortDirection, - order_key: sortHeader, - }, + queryParams: newQueryParams, }); router?.replace(locationPath); }, @@ -251,11 +291,11 @@ const QueriesTable = ({ resultsTitle="queries" columns={tableHeaders} data={queriesList} - filters={{ global: isInherited ? "" : searchQuery }} + filters={{ name: isInherited ? "" : searchQuery }} isLoading={isLoading} defaultSortHeader={sortHeader || DEFAULT_SORT_HEADER} defaultSortDirection={sortDirection || DEFAULT_SORT_DIRECTION} - defaultSearchQuery={searchQuery} + defaultSearchQuery={isInherited ? "" : searchQuery} defaultPageIndex={page} pageSize={DEFAULT_PAGE_SIZE} inputPlaceHolder="Search by name"