diff --git a/changes/33519-url-team-id-param b/changes/33519-url-team-id-param new file mode 100644 index 0000000000..23e305fb08 --- /dev/null +++ b/changes/33519-url-team-id-param @@ -0,0 +1 @@ +- Fleet UI: Host details page includes team_id param in URL to allow retaining team on refresh diff --git a/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx b/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx index a926ac5863..611f8d57a8 100644 --- a/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx +++ b/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx @@ -87,7 +87,7 @@ const lastSeenTime = (status: string, seenTime: string): string => { return "Online"; }; -const allHostTableHeaders: IHostTableColumnConfig[] = [ +const allHostTableHeaders = (teamId?: number): IHostTableColumnConfig[] => [ // We are using React Table useRowSelect functionality for the selection header. // More information on its API can be found here // https://react-table.tanstack.com/docs/api/useRowSelect @@ -158,7 +158,7 @@ const allHostTableHeaders: IHostTableColumnConfig[] = [ return ( { - return allHostTableHeaders.reduce( + return allHostTableHeaders(teamId).reduce( (columns: Column[], currentColumn: Column) => { // skip over column headers that are not shown in free observer tier if (isFreeTier) { @@ -738,17 +740,21 @@ const generateVisibleTableColumns = ({ hiddenColumns, isFreeTier = true, isOnlyObserver = true, + teamId, }: { hiddenColumns: string[]; isFreeTier: boolean | undefined; isOnlyObserver: boolean | undefined; + teamId?: number; }): IHostTableColumnConfig[] => { // remove columns set as hidden by the user. - return generateAvailableTableHeaders({ isFreeTier, isOnlyObserver }).filter( - (column) => { - return !hiddenColumns.includes(column.id as string); - } - ); + return generateAvailableTableHeaders({ + isFreeTier, + isOnlyObserver, + teamId, + }).filter((column) => { + return !hiddenColumns.includes(column.id as string); + }); }; export { diff --git a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx index 84311ac661..6e67fd109f 100644 --- a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx +++ b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx @@ -1568,6 +1568,7 @@ const ManageHostsPage = ({ hiddenColumns: currentHiddenColumns, isFreeTier, isOnlyObserver, + teamId: teamIdForApi, }); const columnIds = tableColumns @@ -1810,6 +1811,7 @@ const ManageHostsPage = ({ isOnlyObserver || isGlobalTechnician || (!isOnGlobalTeam && !isTeamMaintainerOrTeamAdmin), + teamId: teamIdForApi, }); const emptyState = () => { diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx index 27a49bdf06..f030629775 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx @@ -163,6 +163,7 @@ interface IHostDetailsProps { query?: string; order_key?: string; order_direction?: "asc" | "desc"; + team_id?: string; }; search?: string; }; @@ -973,7 +974,7 @@ const HostDetailsPage = ({ const onClickAddQuery = () => { router.push( getPathWithQueryParams(PATHS.NEW_QUERY, { - team_id: currentTeam?.id, + team_id: currentTeam?.id || location.query.team_id, host_id: hostIdFromURL, }) ); @@ -1097,12 +1098,20 @@ const HostDetailsPage = ({ const navigateToNav = (i: number): void => { const navPath = hostDetailsSubNav[i].pathname; - router.push(navPath); + router.push( + getPathWithQueryParams(navPath, { + team_id: currentTeam?.id || location.query.team_id, + }) + ); }; const navigateToSoftwareTab = (i: number): void => { const navPath = hostSoftwareSubNav[i].pathname; - router.push(navPath); + router.push( + getPathWithQueryParams(navPath, { + team_id: currentTeam?.id || location.query.team_id, + }) + ); }; const isHostTeamAdmin = permissions.isTeamAdmin(currentUser, host?.team_id); @@ -1285,7 +1294,12 @@ const HostDetailsPage = ({
diff --git a/frontend/pages/hosts/details/HostQueryReport/HostQueryReport.tsx b/frontend/pages/hosts/details/HostQueryReport/HostQueryReport.tsx index 7f61c6983f..dc4bb0c5f7 100644 --- a/frontend/pages/hosts/details/HostQueryReport/HostQueryReport.tsx +++ b/frontend/pages/hosts/details/HostQueryReport/HostQueryReport.tsx @@ -119,7 +119,7 @@ const HostQueryReport = ({
diff --git a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibrary.tsx b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibrary.tsx index 1d393d8253..a053a7d443 100644 --- a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibrary.tsx +++ b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibrary.tsx @@ -88,6 +88,7 @@ export const parseHostSoftwareLibraryQueryParams = (queryParams: { order_key?: string; order_direction?: "asc" | "desc"; self_service?: string; + team_id?: string; }) => { const searchQuery = queryParams?.query ?? DEFAULT_SEARCH_QUERY; const sortHeader = queryParams?.order_key ?? DEFAULT_SORT_HEADER; @@ -97,6 +98,9 @@ export const parseHostSoftwareLibraryQueryParams = (queryParams: { : DEFAULT_PAGE; const pageSize = DEFAULT_PAGE_SIZE; const selfService = queryParams?.self_service === "true"; + const teamId = queryParams?.team_id + ? parseInt(queryParams.team_id, 10) + : undefined; return { page, @@ -106,6 +110,7 @@ export const parseHostSoftwareLibraryQueryParams = (queryParams: { per_page: pageSize, available_for_install: true, // always true for host installers self_service: selfService, + team_id: teamId, }; }; @@ -605,6 +610,7 @@ const HostSoftwareLibrary = ({ page={queryParams.page} pagePath={pathname} selfService={queryParams.self_service} + teamId={queryParams.team_id} /> ); }; diff --git a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibraryTable/HostSoftwareLibraryTable.tsx b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibraryTable/HostSoftwareLibraryTable.tsx index e981bc73a3..a9fc77e18d 100644 --- a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibraryTable/HostSoftwareLibraryTable.tsx +++ b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostSoftwareLibraryTable/HostSoftwareLibraryTable.tsx @@ -41,6 +41,7 @@ interface IHostSoftwareLibraryTableProps { page: number; pagePath: string; selfService: boolean; + teamId?: number; } const HostSoftwareLibraryTable = ({ @@ -56,6 +57,7 @@ const HostSoftwareLibraryTable = ({ selfService, page, pagePath, + teamId, }: IHostSoftwareLibraryTableProps) => { const determineQueryParamChange = useCallback( (newTableQuery: ITableQueryData) => { @@ -85,6 +87,7 @@ const HostSoftwareLibraryTable = ({ order_direction: newTableQuery.sortDirection, order_key: newTableQuery.sortHeader, page: changedParam === "pageIndex" ? newTableQuery.pageIndex : 0, + team_id: teamId, ...(selfService && { self_service: "true" }), }; @@ -125,6 +128,7 @@ const HostSoftwareLibraryTable = ({ orderDirection: sortDirection, orderKey: sortHeader, page: 0, // resets page index + teamId, ...(value === "selfService" && { selfService: true }), }; diff --git a/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx b/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx index c01e243860..cc4aa32a2e 100644 --- a/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx +++ b/frontend/pages/hosts/details/cards/Software/HostSoftware.tsx @@ -81,6 +81,7 @@ export const parseHostSoftwareQueryParams = (queryParams: { max_cvss_score?: string; self_service?: string; category_id?: string; + team_id?: string; }) => { const searchQuery = queryParams?.query ?? DEFAULT_SEARCH_QUERY; const sortHeader = queryParams?.order_key ?? DEFAULT_SORT_HEADER; @@ -96,6 +97,9 @@ export const parseHostSoftwareQueryParams = (queryParams: { ? parseInt(queryParams.category_id, 10) : undefined; const selfService = queryParams?.self_service === "true"; + const teamId = queryParams?.team_id + ? parseInt(queryParams.team_id, 10) + : undefined; return { page, @@ -110,6 +114,7 @@ export const parseHostSoftwareQueryParams = (queryParams: { exploit: softwareVulnFilters.exploit, available_for_install: false, // always false for host software category_id: categoryId, + team_id: teamId, }; }; @@ -228,6 +233,7 @@ const HostSoftware = ({ orderKey: queryParams.order_key, perPage: queryParams.per_page, page: 0, // resets page index + team_id: queryParams.team_id, ...buildSoftwareVulnFiltersQueryParams(vulnFilters), }; @@ -304,6 +310,7 @@ const HostSoftware = ({ min_cvss_score: queryParams.min_cvss_score, max_cvss_score: queryParams.max_cvss_score, })} + teamId={queryParams.team_id} onAddFiltersClick={toggleSoftwareFiltersModal} // for my device software details modal toggling isMyDevicePage={isMyDevicePage} diff --git a/frontend/pages/hosts/details/cards/Software/HostSoftwareTable/HostSoftwareTable.tsx b/frontend/pages/hosts/details/cards/Software/HostSoftwareTable/HostSoftwareTable.tsx index 4dadacdc64..2c22e4e62b 100644 --- a/frontend/pages/hosts/details/cards/Software/HostSoftwareTable/HostSoftwareTable.tsx +++ b/frontend/pages/hosts/details/cards/Software/HostSoftwareTable/HostSoftwareTable.tsx @@ -75,6 +75,7 @@ interface IHostSoftwareTableProps { page: number; pagePath: string; vulnFilters: ISoftwareVulnFiltersParams; + teamId?: number; onAddFiltersClick: () => void; isMyDevicePage?: boolean; onShowInventoryVersions: (software: IHostSoftware) => void; @@ -92,6 +93,7 @@ const HostSoftwareTable = ({ page, pagePath, vulnFilters, + teamId, onAddFiltersClick, isMyDevicePage, onShowInventoryVersions, @@ -124,6 +126,7 @@ const HostSoftwareTable = ({ order_direction: newTableQuery.sortDirection, order_key: newTableQuery.sortHeader, page: changedParam === "pageIndex" ? newTableQuery.pageIndex : 0, + team_id: teamId, ...buildSoftwareVulnFiltersQueryParams(vulnFilters), }; return newQueryParam; diff --git a/frontend/pages/queries/details/QueryDetailsPage/QueryDetailsPage.tsx b/frontend/pages/queries/details/QueryDetailsPage/QueryDetailsPage.tsx index ab109fc839..643a6fcc88 100644 --- a/frontend/pages/queries/details/QueryDetailsPage/QueryDetailsPage.tsx +++ b/frontend/pages/queries/details/QueryDetailsPage/QueryDetailsPage.tsx @@ -257,7 +257,10 @@ const QueryDetailsPage = ({ const backPath = () => { if (filteredQueriesPath) return filteredQueriesPath; - if (hostId) return getPathWithQueryParams(PATHS.HOST_DETAILS(hostId)); + if (hostId) + return getPathWithQueryParams( + PATHS.HOST_DETAILS(hostId, currentTeamId) + ); return getPathWithQueryParams(PATHS.MANAGE_QUERIES, { team_id: currentTeamId, diff --git a/frontend/pages/queries/edit/EditQueryPage.tsx b/frontend/pages/queries/edit/EditQueryPage.tsx index ad65e48987..7d9a4126e4 100644 --- a/frontend/pages/queries/edit/EditQueryPage.tsx +++ b/frontend/pages/queries/edit/EditQueryPage.tsx @@ -381,7 +381,7 @@ const EditQueryPage = ({ } if (hostId) { - return getPathWithQueryParams(PATHS.HOST_DETAILS(hostId)); + return getPathWithQueryParams(PATHS.HOST_DETAILS(hostId, currentTeamId)); } if (filteredQueriesPath) return filteredQueriesPath; diff --git a/frontend/router/paths.ts b/frontend/router/paths.ts index 8a2009eefc..0bebdaa346 100644 --- a/frontend/router/paths.ts +++ b/frontend/router/paths.ts @@ -141,10 +141,10 @@ export default { MANAGE_HOSTS_LABEL: (labelId: number | string): string => { return `${URL_PREFIX}/hosts/manage/labels/${labelId}`; }, - HOST_DETAILS_PAGE: (id: number): string => { - return `${URL_PREFIX}/hosts/${id}`; - }, - HOST_DETAILS: (id: number): string => { + HOST_DETAILS: (id: number, teamId?: number): string => { + if (teamId) { + return `${URL_PREFIX}/hosts/${id}/details?team_id=${teamId}`; + } return `${URL_PREFIX}/hosts/${id}/details`; }, HOST_SCRIPTS: (id: number): string => {