Defer breadcrumbs translations on route definitions (#883)

This commit is contained in:
Jon Koops 2021-07-21 11:20:32 +02:00 committed by GitHub
parent f0412fda25
commit d8d230557e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 85 deletions

View file

@ -74,13 +74,9 @@ export const App = () => {
onReset={() => window.location.reload()} onReset={() => window.location.reload()}
> >
<Switch> <Switch>
{routes(() => {}).map((route, i) => ( {routes.map((route, i) => (
<Route <Route
exact={ exact={route.matchOptions?.exact ?? true}
route.matchOptions?.exact === undefined
? true
: route.matchOptions.exact
}
key={i} key={i}
path={route.path} path={route.path}
component={() => ( component={() => (

View file

@ -35,7 +35,7 @@ export const PageNav: React.FunctionComponent = () => {
type LeftNavProps = { title: string; path: string }; type LeftNavProps = { title: string; path: string };
const LeftNav = ({ title, path }: LeftNavProps) => { const LeftNav = ({ title, path }: LeftNavProps) => {
const route = routes(() => {}).find( const route = routes.find(
(route) => route.path.replace(/\/:.+?(\?|(?:(?!\/).)*|$)/g, "") === path (route) => route.path.replace(/\/:.+?(\?|(?:(?!\/).)*|$)/g, "") === path
); );
if (!route || !hasAccess(route.access)) return <></>; if (!route || !hasAccess(route.access)) return <></>;

View file

@ -1,6 +1,9 @@
import React, { isValidElement } from "react"; import React, { isValidElement } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import useBreadcrumbs, { BreadcrumbData } from "use-react-router-breadcrumbs"; import useBreadcrumbs, {
BreadcrumbData,
BreadcrumbsRoute,
} from "use-react-router-breadcrumbs";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import _ from "lodash"; import _ from "lodash";
import { Breadcrumb, BreadcrumbItem } from "@patternfly/react-core"; import { Breadcrumb, BreadcrumbItem } from "@patternfly/react-core";
@ -15,8 +18,13 @@ export const PageBreadCrumbs = () => {
const elementText = (crumb: BreadcrumbData) => const elementText = (crumb: BreadcrumbData) =>
isValidElement(crumb.breadcrumb) && crumb.breadcrumb.props.children; isValidElement(crumb.breadcrumb) && crumb.breadcrumb.props.children;
const routesWithCrumbs: BreadcrumbsRoute[] = routes.map((route) => ({
...route,
breadcrumb: route.breadcrumb?.(t),
}));
const crumbs = _.uniqBy( const crumbs = _.uniqBy(
useBreadcrumbs(routes(t), { useBreadcrumbs(routesWithCrumbs, {
excludePaths: ["/", `/${realm}`], excludePaths: ["/", `/${realm}`],
}), }),
elementText elementText

View file

@ -1,261 +1,262 @@
import type { TFunction } from "i18next"; import type { TFunction } from "i18next";
import type { BreadcrumbsRoute } from "use-react-router-breadcrumbs";
import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation"; import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
import type { ComponentType } from "react";
import type { MatchOptions } from "use-react-router-breadcrumbs";
import { AuthenticationSection } from "./authentication/AuthenticationSection"; import { AuthenticationSection } from "./authentication/AuthenticationSection";
import { ClientScopeForm } from "./client-scopes/form/ClientScopeForm"; import { RoleMappingForm } from "./client-scopes/add/RoleMappingForm";
import { ClientScopesSection } from "./client-scopes/ClientScopesSection"; import { ClientScopesSection } from "./client-scopes/ClientScopesSection";
import { DashboardSection } from "./dashboard/Dashboard"; import { MappingDetails } from "./client-scopes/details/MappingDetails";
import { ClientScopeForm } from "./client-scopes/form/ClientScopeForm";
import { NewClientForm } from "./clients/add/NewClientForm"; import { NewClientForm } from "./clients/add/NewClientForm";
import { ClientDetails } from "./clients/ClientDetails";
import { ClientsSection } from "./clients/ClientsSection"; import { ClientsSection } from "./clients/ClientsSection";
import { ImportForm } from "./clients/import/ImportForm"; import { ImportForm } from "./clients/import/ImportForm";
import { CreateInitialAccessToken } from "./clients/initial-access/CreateInitialAccessToken";
import { DashboardSection } from "./dashboard/Dashboard";
import { EventsSection } from "./events/EventsSection"; import { EventsSection } from "./events/EventsSection";
import { GroupsSection } from "./groups/GroupsSection"; import { GroupsSection } from "./groups/GroupsSection";
import { IdentityProvidersSection } from "./identity-providers/IdentityProvidersSection";
import { PageNotFoundSection } from "./PageNotFoundSection";
import { RealmRolesSection } from "./realm-roles/RealmRolesSection";
import {
EditProviderCrumb,
RealmSettingsSection,
} from "./realm-settings/RealmSettingsSection";
import { NewRealmForm } from "./realm/add/NewRealmForm";
import { SessionsSection } from "./sessions/SessionsSection";
import { UserFederationSection } from "./user-federation/UserFederationSection";
import { UsersSection } from "./user/UsersSection";
import { MappingDetails } from "./client-scopes/details/MappingDetails";
import { ClientDetails } from "./clients/ClientDetails";
import { UsersTabs } from "./user/UsersTabs";
import { UserGroups } from "./user/UserGroups";
import { UserFederationKerberosSettings } from "./user-federation/UserFederationKerberosSettings";
import { UserFederationLdapSettings } from "./user-federation/UserFederationLdapSettings";
import { RoleMappingForm } from "./client-scopes/add/RoleMappingForm";
import { RealmRoleTabs } from "./realm-roles/RealmRoleTabs";
import { SearchGroups } from "./groups/SearchGroups"; import { SearchGroups } from "./groups/SearchGroups";
import { CreateInitialAccessToken } from "./clients/initial-access/CreateInitialAccessToken";
import { LdapMapperDetails } from "./user-federation/ldap/mappers/LdapMapperDetails";
import { import {
AddIdentityProvider, AddIdentityProvider,
IdentityProviderCrumb, IdentityProviderCrumb,
} from "./identity-providers/add/AddIdentityProvider"; } from "./identity-providers/add/AddIdentityProvider";
import { AddOpenIdConnect } from "./identity-providers/add/AddOpenIdConnect"; import { AddOpenIdConnect } from "./identity-providers/add/AddOpenIdConnect";
import { DetailSettings } from "./identity-providers/add/DetailSettings"; import { DetailSettings } from "./identity-providers/add/DetailSettings";
import { IdentityProvidersSection } from "./identity-providers/IdentityProvidersSection";
import { PageNotFoundSection } from "./PageNotFoundSection";
import { RealmRolesSection } from "./realm-roles/RealmRolesSection";
import { RealmRoleTabs } from "./realm-roles/RealmRoleTabs";
import { AESGeneratedSettings } from "./realm-settings/key-providers/aes-generated/AESGeneratedForm"; import { AESGeneratedSettings } from "./realm-settings/key-providers/aes-generated/AESGeneratedForm";
import { HMACGeneratedSettings } from "./realm-settings/key-providers/hmac-generated/HMACGeneratedForm";
import { RSAGeneratedSettings } from "./realm-settings/key-providers/rsa-generated/RSAGeneratedForm";
import { ECDSAGeneratedSettings } from "./realm-settings/key-providers/ecdsa-generated/ECDSAGeneratedForm"; import { ECDSAGeneratedSettings } from "./realm-settings/key-providers/ecdsa-generated/ECDSAGeneratedForm";
import { HMACGeneratedSettings } from "./realm-settings/key-providers/hmac-generated/HMACGeneratedForm";
import { JavaKeystoreSettings } from "./realm-settings/key-providers/java-keystore/JavaKeystoreForm"; import { JavaKeystoreSettings } from "./realm-settings/key-providers/java-keystore/JavaKeystoreForm";
import { RSAGeneratedSettings } from "./realm-settings/key-providers/rsa-generated/RSAGeneratedForm";
import { RSASettings } from "./realm-settings/key-providers/rsa/RSAForm"; import { RSASettings } from "./realm-settings/key-providers/rsa/RSAForm";
import {
EditProviderCrumb,
RealmSettingsSection,
} from "./realm-settings/RealmSettingsSection";
import { NewRealmForm } from "./realm/add/NewRealmForm";
import { SessionsSection } from "./sessions/SessionsSection";
import { LdapMapperDetails } from "./user-federation/ldap/mappers/LdapMapperDetails";
import { UserFederationKerberosSettings } from "./user-federation/UserFederationKerberosSettings";
import { UserFederationLdapSettings } from "./user-federation/UserFederationLdapSettings";
import { UserFederationSection } from "./user-federation/UserFederationSection";
import { UserGroups } from "./user/UserGroups";
import { UsersSection } from "./user/UsersSection";
import { UsersTabs } from "./user/UsersTabs";
export type RouteDef = BreadcrumbsRoute & { export type RouteDef = {
path: string;
component: ComponentType;
breadcrumb: ((t: TFunction) => string | ComponentType<any>) | null;
access: AccessType; access: AccessType;
component: () => JSX.Element; matchOptions?: MatchOptions;
}; };
type RoutesFn = (t: TFunction) => RouteDef[]; export const routes: RouteDef[] = [
export const routes: RoutesFn = (t: TFunction) => [
{ {
path: "/:realm/add-realm", path: "/:realm/add-realm",
component: NewRealmForm, component: NewRealmForm,
breadcrumb: t("realm:createRealm"), breadcrumb: (t) => t("realm:createRealm"),
access: "manage-realm", access: "manage-realm",
}, },
{ {
path: "/:realm/clients/add-client", path: "/:realm/clients/add-client",
component: NewClientForm, component: NewClientForm,
breadcrumb: t("clients:createClient"), breadcrumb: (t) => t("clients:createClient"),
access: "manage-clients", access: "manage-clients",
}, },
{ {
path: "/:realm/clients/import-client", path: "/:realm/clients/import-client",
component: ImportForm, component: ImportForm,
breadcrumb: t("clients:importClient"), breadcrumb: (t) => t("clients:importClient"),
access: "manage-clients", access: "manage-clients",
}, },
{ {
path: "/:realm/clients/:tab?", path: "/:realm/clients/:tab?",
component: ClientsSection, component: ClientsSection,
breadcrumb: t("clients:clientList"), breadcrumb: (t) => t("clients:clientList"),
access: "query-clients", access: "query-clients",
}, },
{ {
path: "/:realm/clients/initialAccessToken/create", path: "/:realm/clients/initialAccessToken/create",
component: CreateInitialAccessToken, component: CreateInitialAccessToken,
breadcrumb: t("clients:createToken"), breadcrumb: (t) => t("clients:createToken"),
access: "manage-clients", access: "manage-clients",
}, },
{ {
path: "/:realm/clients/:clientId/roles/add-role", path: "/:realm/clients/:clientId/roles/add-role",
component: RealmRoleTabs, component: RealmRoleTabs,
breadcrumb: t("roles:createRole"), breadcrumb: (t) => t("roles:createRole"),
access: "manage-realm", access: "manage-realm",
}, },
{ {
path: "/:realm/clients/:clientId/roles/:id/:tab?", path: "/:realm/clients/:clientId/roles/:id/:tab?",
component: RealmRoleTabs, component: RealmRoleTabs,
breadcrumb: t("roles:roleDetails"), breadcrumb: (t) => t("roles:roleDetails"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/clients/:clientId/:tab", path: "/:realm/clients/:clientId/:tab",
component: ClientDetails, component: ClientDetails,
breadcrumb: t("clients:clientSettings"), breadcrumb: (t) => t("clients:clientSettings"),
access: "view-clients", access: "view-clients",
}, },
{ {
path: "/:realm/client-scopes/new", path: "/:realm/client-scopes/new",
component: ClientScopeForm, component: ClientScopeForm,
breadcrumb: t("client-scopes:createClientScope"), breadcrumb: (t) => t("client-scopes:createClientScope"),
access: "manage-clients", access: "manage-clients",
}, },
{ {
path: "/:realm/client-scopes/:id/mappers/oidc-role-name-mapper", path: "/:realm/client-scopes/:id/mappers/oidc-role-name-mapper",
component: RoleMappingForm, component: RoleMappingForm,
breadcrumb: t("common:mappingDetails"), breadcrumb: (t) => t("common:mappingDetails"),
access: "view-clients", access: "view-clients",
}, },
{ {
path: "/:realm/client-scopes/:id/mappers/:mapperId", path: "/:realm/client-scopes/:id/mappers/:mapperId",
component: MappingDetails, component: MappingDetails,
breadcrumb: t("common:mappingDetails"), breadcrumb: (t) => t("common:mappingDetails"),
access: "view-clients", access: "view-clients",
}, },
{ {
path: "/:realm/client-scopes/:id/:type/:tab", path: "/:realm/client-scopes/:id/:type/:tab",
component: ClientScopeForm, component: ClientScopeForm,
breadcrumb: t("client-scopes:clientScopeDetails"), breadcrumb: (t) => t("client-scopes:clientScopeDetails"),
access: "view-clients", access: "view-clients",
}, },
{ {
path: "/:realm/client-scopes", path: "/:realm/client-scopes",
component: ClientScopesSection, component: ClientScopesSection,
breadcrumb: t("client-scopes:clientScopeList"), breadcrumb: (t) => t("client-scopes:clientScopeList"),
access: "view-clients", access: "view-clients",
}, },
{ {
path: "/:realm/roles", path: "/:realm/roles",
component: RealmRolesSection, component: RealmRolesSection,
breadcrumb: t("roles:roleList"), breadcrumb: (t) => t("roles:roleList"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/roles/add-role", path: "/:realm/roles/add-role",
component: RealmRoleTabs, component: RealmRoleTabs,
breadcrumb: t("roles:createRole"), breadcrumb: (t) => t("roles:createRole"),
access: "manage-realm", access: "manage-realm",
}, },
{ {
path: "/:realm/roles/:id/:tab?", path: "/:realm/roles/:id/:tab?",
component: RealmRoleTabs, component: RealmRoleTabs,
breadcrumb: t("roles:roleDetails"), breadcrumb: (t) => t("roles:roleDetails"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/users", path: "/:realm/users",
component: UsersSection, component: UsersSection,
breadcrumb: t("users:title"), breadcrumb: (t) => t("users:title"),
access: "query-users", access: "query-users",
}, },
{ {
path: "/:realm/users/add-user", path: "/:realm/users/add-user",
component: UsersTabs, component: UsersTabs,
breadcrumb: t("users:createUser"), breadcrumb: (t) => t("users:createUser"),
access: "manage-users", access: "manage-users",
}, },
{ {
path: "/:realm/users/:id", path: "/:realm/users/:id",
component: UserGroups, component: UserGroups,
breadcrumb: t("users:userDetails"), breadcrumb: (t) => t("users:userDetails"),
access: "manage-users", access: "manage-users",
}, },
{ {
path: "/:realm/users/:id/:tab", path: "/:realm/users/:id/:tab",
component: UsersTabs, component: UsersTabs,
breadcrumb: t("users:userDetails"), breadcrumb: (t) => t("users:userDetails"),
access: "manage-users", access: "manage-users",
}, },
{ {
path: "/:realm/sessions", path: "/:realm/sessions",
component: SessionsSection, component: SessionsSection,
breadcrumb: t("sessions:title"), breadcrumb: (t) => t("sessions:title"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/events/:tab?", path: "/:realm/events/:tab?",
component: EventsSection, component: EventsSection,
breadcrumb: t("events:title"), breadcrumb: (t) => t("events:title"),
access: "view-events", access: "view-events",
}, },
{ {
path: "/:realm/realm-settings/:tab?", path: "/:realm/realm-settings/:tab?",
component: RealmSettingsSection, component: RealmSettingsSection,
breadcrumb: t("realmSettings"), breadcrumb: (t) => t("realmSettings"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/realm-settings/keys/:id?/aes-generated/settings", path: "/:realm/realm-settings/keys/:id?/aes-generated/settings",
component: AESGeneratedSettings, component: AESGeneratedSettings,
breadcrumb: EditProviderCrumb, breadcrumb: () => EditProviderCrumb,
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/realm-settings/keys/:id?/ecdsa-generated/settings", path: "/:realm/realm-settings/keys/:id?/ecdsa-generated/settings",
component: ECDSAGeneratedSettings, component: ECDSAGeneratedSettings,
breadcrumb: EditProviderCrumb, breadcrumb: () => EditProviderCrumb,
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/realm-settings/keys/:id?/hmac-generated/settings", path: "/:realm/realm-settings/keys/:id?/hmac-generated/settings",
component: HMACGeneratedSettings, component: HMACGeneratedSettings,
breadcrumb: EditProviderCrumb, breadcrumb: () => EditProviderCrumb,
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/realm-settings/keys/:id?/java-keystore/settings", path: "/:realm/realm-settings/keys/:id?/java-keystore/settings",
component: JavaKeystoreSettings, component: JavaKeystoreSettings,
breadcrumb: EditProviderCrumb, breadcrumb: () => EditProviderCrumb,
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/realm-settings/keys/:id?/rsa-generated/settings", path: "/:realm/realm-settings/keys/:id?/rsa-generated/settings",
component: RSAGeneratedSettings, component: RSAGeneratedSettings,
breadcrumb: EditProviderCrumb, breadcrumb: () => EditProviderCrumb,
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/realm-settings/keys/:id?/rsa/settings", path: "/:realm/realm-settings/keys/:id?/rsa/settings",
component: RSASettings, component: RSASettings,
breadcrumb: EditProviderCrumb, breadcrumb: () => EditProviderCrumb,
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/authentication", path: "/:realm/authentication",
component: AuthenticationSection, component: AuthenticationSection,
breadcrumb: t("authentication"), breadcrumb: (t) => t("authentication"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/identity-providers", path: "/:realm/identity-providers",
component: IdentityProvidersSection, component: IdentityProvidersSection,
breadcrumb: t("identityProviders"), breadcrumb: (t) => t("identityProviders"),
access: "view-identity-providers", access: "view-identity-providers",
}, },
{ {
path: "/:realm/identity-providers/oidc", path: "/:realm/identity-providers/oidc",
component: AddOpenIdConnect, component: AddOpenIdConnect,
breadcrumb: t("identity-providers:addOpenIdProvider"), breadcrumb: (t) => t("identity-providers:addOpenIdProvider"),
access: "manage-identity-providers", access: "manage-identity-providers",
}, },
{ {
path: "/:realm/identity-providers/keycloak-oidc", path: "/:realm/identity-providers/keycloak-oidc",
component: AddOpenIdConnect, component: AddOpenIdConnect,
breadcrumb: t("identity-providers:addKeycloakOpenIdProvider"), breadcrumb: (t) => t("identity-providers:addKeycloakOpenIdProvider"),
access: "manage-identity-providers", access: "manage-identity-providers",
}, },
{ {
path: "/:realm/identity-providers/:id", path: "/:realm/identity-providers/:id",
component: AddIdentityProvider, component: AddIdentityProvider,
breadcrumb: IdentityProviderCrumb, breadcrumb: () => IdentityProviderCrumb,
access: "manage-identity-providers", access: "manage-identity-providers",
}, },
{ {
@ -267,7 +268,7 @@ export const routes: RoutesFn = (t: TFunction) => [
{ {
path: "/:realm/user-federation", path: "/:realm/user-federation",
component: UserFederationSection, component: UserFederationSection,
breadcrumb: t("userFederation"), breadcrumb: (t) => t("userFederation"),
access: "view-realm", access: "view-realm",
}, },
{ {
@ -279,13 +280,13 @@ export const routes: RoutesFn = (t: TFunction) => [
{ {
path: "/:realm/user-federation/kerberos/:id", path: "/:realm/user-federation/kerberos/:id",
component: UserFederationKerberosSettings, component: UserFederationKerberosSettings,
breadcrumb: t("common:settings"), breadcrumb: (t) => t("common:settings"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/user-federation/kerberos/new", path: "/:realm/user-federation/kerberos/new",
component: UserFederationKerberosSettings, component: UserFederationKerberosSettings,
breadcrumb: t("common:settings"), breadcrumb: (t) => t("common:settings"),
access: "view-realm", access: "view-realm",
}, },
{ {
@ -297,46 +298,46 @@ export const routes: RoutesFn = (t: TFunction) => [
{ {
path: "/:realm/user-federation/ldap/new", path: "/:realm/user-federation/ldap/new",
component: UserFederationLdapSettings, component: UserFederationLdapSettings,
breadcrumb: t("user-federation:addOneLdap"), breadcrumb: (t) => t("user-federation:addOneLdap"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/user-federation/ldap/:id/:tab?", path: "/:realm/user-federation/ldap/:id/:tab?",
component: UserFederationLdapSettings, component: UserFederationLdapSettings,
breadcrumb: t("common:settings"), breadcrumb: (t) => t("common:settings"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/user-federation/ldap/:id/:tab/:mapperId", path: "/:realm/user-federation/ldap/:id/:tab/:mapperId",
component: LdapMapperDetails, component: LdapMapperDetails,
breadcrumb: t("common:mappingDetails"), breadcrumb: (t) => t("common:mappingDetails"),
access: "view-realm", access: "view-realm",
}, },
{ {
path: "/:realm/", path: "/:realm/",
component: DashboardSection, component: DashboardSection,
breadcrumb: t("common:home"), breadcrumb: (t) => t("common:home"),
access: "anyone", access: "anyone",
}, },
{ {
path: "/:realm/groups/search", path: "/:realm/groups/search",
component: SearchGroups, component: SearchGroups,
breadcrumb: t("groups:searchGroups"), breadcrumb: (t) => t("groups:searchGroups"),
access: "query-groups", access: "query-groups",
}, },
{ {
path: "/:realm/groups", path: "/:realm/groups",
component: GroupsSection, component: GroupsSection,
breadcrumb: null, breadcrumb: null,
access: "query-groups",
matchOptions: { matchOptions: {
exact: false, exact: false,
}, },
access: "query-groups",
}, },
{ {
path: "/", path: "/",
component: DashboardSection, component: DashboardSection,
breadcrumb: t("common:home"), breadcrumb: (t) => t("common:home"),
access: "anyone", access: "anyone",
}, },
{ {