diff --git a/changes/issue-8504-routes-for-dashboard-platform b/changes/issue-8504-routes-for-dashboard-platform new file mode 100644 index 0000000000..9deea3dead --- /dev/null +++ b/changes/issue-8504-routes-for-dashboard-platform @@ -0,0 +1 @@ +- New URL routes for dashboard platforms diff --git a/frontend/components/top_nav/SiteTopNav/navItems.ts b/frontend/components/top_nav/SiteTopNav/navItems.ts index 49dbeb0140..2cfb9da172 100644 --- a/frontend/components/top_nav/SiteTopNav/navItems.ts +++ b/frontend/components/top_nav/SiteTopNav/navItems.ts @@ -32,7 +32,7 @@ export default ( iconName: "logo", location: { regex: new RegExp(`^${URL_PREFIX}/dashboard`), - pathname: PATHS.HOME, + pathname: PATHS.DASHBOARD, }, }, ]; diff --git a/frontend/docs/patterns.md b/frontend/docs/patterns.md index c1ad1b9974..318868307d 100644 --- a/frontend/docs/patterns.md +++ b/frontend/docs/patterns.md @@ -248,7 +248,7 @@ const PageOrComponent = ({ router, }: IPageProps) => { const doSomething = () => { - router.push(PATHS.HOME); + router.push(PATHS.DASHBOARD); }; return ( diff --git a/frontend/pages/ApiOnlyUser/ApiOnlyUser.tsx b/frontend/pages/ApiOnlyUser/ApiOnlyUser.tsx index c3b0b9c2cf..7248530eeb 100644 --- a/frontend/pages/ApiOnlyUser/ApiOnlyUser.tsx +++ b/frontend/pages/ApiOnlyUser/ApiOnlyUser.tsx @@ -15,7 +15,7 @@ interface IApiOnlyUserProps { const baseClass = "api-only-user"; const ApiOnlyUser = ({ router }: IApiOnlyUserProps): JSX.Element => { - const { LOGIN, HOME, LOGOUT } = paths; + const { LOGIN, DASHBOARD, LOGOUT } = paths; const handleClick = () => router.push(LOGOUT); useEffect(() => { @@ -26,7 +26,7 @@ const ApiOnlyUser = ({ router }: IApiOnlyUserProps): JSX.Element => { if (!user) { router.push(LOGIN); } else if (!user?.api_only) { - router.push(HOME); + router.push(DASHBOARD); } } catch (response) { console.error(response); diff --git a/frontend/pages/ConfirmInvitePage/ConfirmInvitePage.tsx b/frontend/pages/ConfirmInvitePage/ConfirmInvitePage.tsx index c26c33099e..1aa1c153f6 100644 --- a/frontend/pages/ConfirmInvitePage/ConfirmInvitePage.tsx +++ b/frontend/pages/ConfirmInvitePage/ConfirmInvitePage.tsx @@ -34,10 +34,10 @@ const ConfirmInvitePage = ({ const [userErrors, setUserErrors] = useState({}); useEffect(() => { - const { HOME } = paths; + const { DASHBOARD } = paths; if (currentUser) { - return router.push(HOME); + return router.push(DASHBOARD); } }, [currentUser]); diff --git a/frontend/pages/ConfirmSSOInvitePage/ConfirmSSOInvitePage.tsx b/frontend/pages/ConfirmSSOInvitePage/ConfirmSSOInvitePage.tsx index 14ddc4569d..21b83ef694 100644 --- a/frontend/pages/ConfirmSSOInvitePage/ConfirmSSOInvitePage.tsx +++ b/frontend/pages/ConfirmSSOInvitePage/ConfirmSSOInvitePage.tsx @@ -32,21 +32,21 @@ const ConfirmSSOInvitePage = ({ const [errors, setErrors] = useState<{ [key: string]: string }>({}); useEffect(() => { - const { HOME } = paths; + const { DASHBOARD } = paths; if (currentUser) { - return router.push(HOME); + return router.push(DASHBOARD); } }, [currentUser]); const onSubmit = async (formData: any) => { - const { HOME } = paths; + const { DASHBOARD } = paths; formData.sso_invite = true; try { await usersAPI.create(formData); - const { url } = await sessionsAPI.initializeSSO(HOME); + const { url } = await sessionsAPI.initializeSSO(DASHBOARD); window.location.href = url; } catch (response) { const errorObject = formatErrorResponse(response); diff --git a/frontend/pages/DashboardPage/DashboardPage.tsx b/frontend/pages/DashboardPage/DashboardPage.tsx index cd5f554ef3..5b624a3e4c 100644 --- a/frontend/pages/DashboardPage/DashboardPage.tsx +++ b/frontend/pages/DashboardPage/DashboardPage.tsx @@ -1,4 +1,5 @@ import React, { useContext, useState, useEffect } from "react"; +import { InjectedRouter } from "react-router"; import { useQuery } from "react-query"; import { AppContext } from "context/app"; import { find } from "lodash"; @@ -56,7 +57,17 @@ const baseClass = "dashboard-page"; // Premium feature, Gb must be set between 1-100 const LOW_DISK_SPACE_GB = 32; -const DashboardPage = (): JSX.Element => { +interface IDashboardProps { + router: InjectedRouter; // v3 + location: { + pathname: string; + }; +} + +const DashboardPage = ({ + router, + location: { pathname }, +}: IDashboardProps): JSX.Element => { const { config, currentTeam, @@ -114,6 +125,14 @@ const DashboardPage = (): JSX.Element => { JSX.Element | string | null >(); + useEffect(() => { + const platformByPathname = + PLATFORM_DROPDOWN_OPTIONS?.find((platform) => platform.path === pathname) + ?.value || "all"; + + setSelectedPlatform(platformByPathname); + }, [pathname]); + const canEnrollHosts = isGlobalAdmin || isGlobalMaintainer || isTeamAdmin || isTeamMaintainer; const canEnrollGlobalHosts = isGlobalAdmin || isGlobalMaintainer; @@ -633,7 +652,10 @@ const DashboardPage = (): JSX.Element => { options={PLATFORM_DROPDOWN_OPTIONS} searchable={false} onChange={(value: ISelectedPlatform) => { - setSelectedPlatform(value); + const selectedPlatformOption = PLATFORM_DROPDOWN_OPTIONS.find( + (platform) => platform.value === value + ); + router.push(selectedPlatformOption?.path || paths.DASHBOARD); }} /> diff --git a/frontend/pages/LoginPage/LoginPage.tsx b/frontend/pages/LoginPage/LoginPage.tsx index 05c4644d4b..43415c977e 100644 --- a/frontend/pages/LoginPage/LoginPage.tsx +++ b/frontend/pages/LoginPage/LoginPage.tsx @@ -63,7 +63,7 @@ const LoginPage = ({ router, location }: ILoginPageProps) => { const [errors, setErrors] = useState<{ [key: string]: string }>({}); useEffect(() => { - const { HOME } = paths; + const { DASHBOARD } = paths; const getSSO = async () => { try { const { settings } = await sessionsAPI.ssoSettings(); @@ -79,7 +79,7 @@ const LoginPage = ({ router, location }: ILoginPageProps) => { } if (currentUser && !currentUser.force_password_reset) { - router?.push(HOME); + router?.push(DASHBOARD); } if (pageStatus && pageStatus in statusMessages) { @@ -96,7 +96,7 @@ const LoginPage = ({ router, location }: ILoginPageProps) => { }; const onSubmit = async (formData: ILoginData) => { - const { HOME, RESET_PASSWORD } = paths; + const { DASHBOARD, RESET_PASSWORD } = paths; try { const { user, available_teams, token } = await sessionsAPI.create( @@ -114,7 +114,7 @@ const LoginPage = ({ router, location }: ILoginPageProps) => { if (user.force_password_reset) { return router.push(RESET_PASSWORD); } - return router.push(redirectLocation || HOME); + return router.push(redirectLocation || DASHBOARD); } catch (response) { const errorObject = formatErrorResponse(response); setErrors(errorObject); @@ -123,8 +123,8 @@ const LoginPage = ({ router, location }: ILoginPageProps) => { }; const ssoSignOn = async () => { - const { HOME } = paths; - let returnToAfterAuth = HOME; + const { DASHBOARD } = paths; + let returnToAfterAuth = DASHBOARD; if (redirectLocation != null) { returnToAfterAuth = redirectLocation; } diff --git a/frontend/pages/LoginPage/LoginPreviewPage.tsx b/frontend/pages/LoginPage/LoginPreviewPage.tsx index 6d2d9ad10c..28228239d8 100644 --- a/frontend/pages/LoginPage/LoginPreviewPage.tsx +++ b/frontend/pages/LoginPage/LoginPreviewPage.tsx @@ -29,7 +29,7 @@ const LoginPreviewPage = ({ router }: ILoginPreviewPageProps): JSX.Element => { const [loginVisible, setLoginVisible] = useState(true); const onSubmit = async (formData: ILoginData) => { - const { HOME } = paths; + const { DASHBOARD } = paths; try { const { user, available_teams, token } = await sessionsAPI.create( @@ -42,7 +42,7 @@ const LoginPreviewPage = ({ router }: ILoginPreviewPageProps): JSX.Element => { setAvailableTeams(available_teams); setCurrentTeam(undefined); - return router.push(HOME); + return router.push(DASHBOARD); } catch (response) { console.error(response); return false; diff --git a/frontend/pages/RegistrationPage/RegistrationPage.tsx b/frontend/pages/RegistrationPage/RegistrationPage.tsx index 40d87a85b4..2554313a97 100644 --- a/frontend/pages/RegistrationPage/RegistrationPage.tsx +++ b/frontend/pages/RegistrationPage/RegistrationPage.tsx @@ -38,10 +38,10 @@ const RegistrationPage = ({ router }: IRegistrationPageProps) => { const [showSetupError, setShowSetupError] = useState(false); useEffect(() => { - const { HOME } = paths; + const { DASHBOARD } = paths; if (currentUser) { - return router.push(HOME); + return router.push(DASHBOARD); } }, [currentUser]); diff --git a/frontend/pages/ResetPasswordPage/ResetPasswordPage.tsx b/frontend/pages/ResetPasswordPage/ResetPasswordPage.tsx index 32f11926cf..89015145ef 100644 --- a/frontend/pages/ResetPasswordPage/ResetPasswordPage.tsx +++ b/frontend/pages/ResetPasswordPage/ResetPasswordPage.tsx @@ -43,7 +43,7 @@ const ResetPasswordPage = ({ location, router }: IResetPasswordPageProps) => { await usersAPI.performRequiredPasswordReset(new_password as string); const config = await configAPI.loadAll(); setConfig(config); - return router.push(PATHS.HOME); + return router.push(PATHS.DASHBOARD); } catch (response) { const errorObject = formatErrorResponse(response); setErrors(errorObject); diff --git a/frontend/pages/errors/Fleet403/Fleet403.tsx b/frontend/pages/errors/Fleet403/Fleet403.tsx index c29c04fd6e..c15f8bee25 100644 --- a/frontend/pages/errors/Fleet403/Fleet403.tsx +++ b/frontend/pages/errors/Fleet403/Fleet403.tsx @@ -13,7 +13,7 @@ const baseClass = "fleet-403"; const Fleet403 = () => (
- + (
- + (
- + - - + + + + + + diff --git a/frontend/router/paths.ts b/frontend/router/paths.ts index ab27a34290..412a453fca 100644 --- a/frontend/router/paths.ts +++ b/frontend/router/paths.ts @@ -5,7 +5,10 @@ import URL_PREFIX from "./url_prefix"; export default { ROOT: `${URL_PREFIX}/`, - HOME: `${URL_PREFIX}/dashboard`, + DASHBOARD: `${URL_PREFIX}/dashboard`, + DASHBOARD_LINUX: `${URL_PREFIX}/dashboard/linux`, + DASHBOARD_MAC: `${URL_PREFIX}/dashboard/mac`, + DASHBOARD_WINDOWS: `${URL_PREFIX}/dashboard/windows`, ADMIN_USERS: `${URL_PREFIX}/settings/users`, ADMIN_INTEGRATIONS: `${URL_PREFIX}/settings/integrations`, ADMIN_TEAMS: `${URL_PREFIX}/settings/teams`, diff --git a/frontend/utilities/constants.ts b/frontend/utilities/constants.ts index 0ecaa29677..52cc7a8c98 100644 --- a/frontend/utilities/constants.ts +++ b/frontend/utilities/constants.ts @@ -1,5 +1,6 @@ import URL_PREFIX from "router/url_prefix"; import { IOsqueryPlatform } from "interfaces/platform"; +import paths from "router/paths"; const { origin } = global.window.location; export const BASE_URL = `${origin}${URL_PREFIX}/api`; @@ -167,11 +168,16 @@ export const PLATFORM_LABEL_DISPLAY_TYPES: Record = { "Ubuntu Linux": "platform", }; -export const PLATFORM_DROPDOWN_OPTIONS = [ - { label: "All", value: "all" }, - { label: "Windows", value: "windows" }, - { label: "Linux", value: "linux" }, - { label: "macOS", value: "darwin" }, +interface IPlatformDropdownOptions { + label: "All" | "Windows" | "Linux" | "macOS"; + value: "all" | "windows" | "linux" | "darwin"; + path: string; +} +export const PLATFORM_DROPDOWN_OPTIONS: IPlatformDropdownOptions[] = [ + { label: "All", value: "all", path: paths.DASHBOARD }, + { label: "Windows", value: "windows", path: paths.DASHBOARD_WINDOWS }, + { label: "Linux", value: "linux", path: paths.DASHBOARD_LINUX }, + { label: "macOS", value: "darwin", path: paths.DASHBOARD_MAC }, ]; export const PLATFORM_NAME_TO_LABEL_NAME = {