diff --git a/public/resources/en/dashboard.json b/public/resources/en/dashboard.json index f99b008b18..c49d71d8ff 100644 --- a/public/resources/en/dashboard.json +++ b/public/resources/en/dashboard.json @@ -12,5 +12,9 @@ "infoEnabledFeatures": "Something about what enabled features are.", "infoDisabledFeatures": "Something about what disabled features are.", "disabledFeatures": "Disabled features", - "adminUiVersion": "<0 className=\"pf-u-mr-md\">Admin UI version{{version}}" + "adminUiVersion": "<0 className=\"pf-u-mr-md\">Admin UI version{{version}}", + "providerInfo": "Provider info", + "providers": "Providers", + "realmInfo": "Realm info", + "spi": "SPI" } \ No newline at end of file diff --git a/src/dashboard/Dashboard.tsx b/src/dashboard/Dashboard.tsx index 9a4c0b0a5f..4f24a9baf6 100644 --- a/src/dashboard/Dashboard.tsx +++ b/src/dashboard/Dashboard.tsx @@ -1,3 +1,7 @@ +import React from "react"; +import { useHistory } from "react-router-dom"; +import { Trans, useTranslation } from "react-i18next"; +import { xor } from "lodash-es"; import { Brand, Card, @@ -16,22 +20,34 @@ import { ListItem, ListVariant, PageSection, + Tab, + TabTitleText, Text, TextContent, Title, } from "@patternfly/react-core"; -import React from "react"; -import { Trans, useTranslation } from "react-i18next"; -import { xor } from "lodash-es"; +import { + TableComposable, + Tbody, + Td, + Th, + Thead, + Tr, +} from "@patternfly/react-table"; import { useRealm } from "../context/realm-context/RealmContext"; import { useServerInfo } from "../context/server-info/ServerInfoProvider"; import { toUpperCase } from "../util"; import { HelpItem } from "../components/help-enabler/HelpItem"; import environment from "../environment"; +import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; +import { + routableTab, + RoutableTabs, +} from "../components/routable-tabs/RoutableTabs"; +import { DashboardTab, toDashboard } from "./routes/Dashboard"; import "./dashboard.css"; -import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; const EmptyDashboard = () => { const { t } = useTranslation("dashboard"); @@ -60,6 +76,7 @@ const Dashboard = () => { const { t } = useTranslation("dashboard"); const { realm } = useRealm(); const serverInfo = useServerInfo(); + const history = useHistory(); const enabledFeatures = xor( serverInfo.profileInfo?.disabledFeatures, @@ -67,18 +84,25 @@ const Dashboard = () => { serverInfo.profileInfo?.previewFeatures ); - const isExperimentalFeature = (feature: string) => { - return serverInfo.profileInfo?.experimentalFeatures?.includes(feature); - }; + const isExperimentalFeature = (feature: string) => + serverInfo.profileInfo?.experimentalFeatures?.includes(feature); - const isPreviewFeature = (feature: string) => { - return serverInfo.profileInfo?.previewFeatures?.includes(feature); - }; + const isPreviewFeature = (feature: string) => + serverInfo.profileInfo?.previewFeatures?.includes(feature); if (Object.keys(serverInfo).length === 0) { return ; } + const route = (tab: DashboardTab) => + routableTab({ + to: toDashboard({ + realm, + tab, + }), + history, + }); + return ( <> @@ -94,79 +118,138 @@ const Dashboard = () => { - - - - - {t("serverInfo")} - - - - {t("version")} - - {serverInfo.systemInfo?.version} - - {t("product")} - - {toUpperCase(serverInfo.profileInfo?.name!)} - - - - - - - - - {t("profile")} - - - - - {t("enabledFeatures")}{" "} - - - - - {enabledFeatures.map((feature) => ( - - {feature}{" "} - {isExperimentalFeature(feature) ? ( - - ) : null} - {isPreviewFeature(feature) ? ( - - ) : null} - - ))} - - - - - - {t("disabledFeatures")}{" "} - - - - - {serverInfo.profileInfo?.disabledFeatures?.map( - (feature) => ( - {feature} - ) - )} - - - - - - - - + + + {t("realmInfo")}} + {...route("info")} + > + + + + + {t("serverInfo")} + + + + + {t("version")} + + + {serverInfo.systemInfo?.version} + + + {t("product")} + + + {toUpperCase(serverInfo.profileInfo?.name!)} + + + + + + + + + {t("profile")} + + + + + {t("enabledFeatures")}{" "} + + + + + {enabledFeatures.map((feature) => ( + + {feature}{" "} + {isExperimentalFeature(feature) ? ( + + ) : null} + {isPreviewFeature(feature) ? ( + + ) : null} + + ))} + + + + + + {t("disabledFeatures")}{" "} + + + + + {serverInfo.profileInfo?.disabledFeatures?.map( + (feature) => ( + {feature} + ) + )} + + + + + + + + + + + {t("providerInfo")}} + {...route("providers")} + > + + + + + {t("spi")} + {t("providers")} + + + + {Object.keys(serverInfo.providers || []).map((name) => ( + + {name} + +
    + {Object.keys( + serverInfo.providers?.[name].providers || [] + ).map((value) => ( +
  • {value}
  • + ))} +
+ + + ))} + +
+
    +
    +
    +
    ); diff --git a/src/dashboard/routes/Dashboard.ts b/src/dashboard/routes/Dashboard.ts index 05942518ff..255bd6783a 100644 --- a/src/dashboard/routes/Dashboard.ts +++ b/src/dashboard/routes/Dashboard.ts @@ -3,10 +3,12 @@ import { lazy } from "react"; import { generatePath } from "react-router-dom"; import type { RouteDef } from "../../route-config"; -export type DashboardParams = { realm?: string }; +export type DashboardTab = "info" | "providers"; + +export type DashboardParams = { realm?: string; tab?: DashboardTab }; export const DashboardRoute: RouteDef = { - path: "/:realm?", + path: "/:realm?/:tab?", component: lazy(() => import("../Dashboard")), breadcrumb: (t) => t("common:home"), access: "anyone", diff --git a/src/route-config.ts b/src/route-config.ts index 9f89086890..d72f54e32b 100644 --- a/src/route-config.ts +++ b/src/route-config.ts @@ -43,7 +43,7 @@ export const routes: RouteDef[] = [ ...sessionRoutes, ...userFederationRoutes, ...userRoutes, - ...dashboardRoutes, ...groupsRoutes, + ...dashboardRoutes, NotFoundRoute, ];