Refactor roles list to React Router v6 (#4187)
This commit is contained in:
parent
2b9744f6bf
commit
d11ed1ccef
12 changed files with 103 additions and 118 deletions
|
@ -31,6 +31,7 @@ import { DownloadDialog } from "../components/download-dialog/DownloadDialog";
|
|||
import type { KeyValueType } from "../components/key-value-form/key-value-convert";
|
||||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { PermissionsTab } from "../components/permission-tab/PermissionTab";
|
||||
import { RolesList } from "../components/roles-list/RolesList";
|
||||
import {
|
||||
RoutableTabs,
|
||||
useRoutableTab,
|
||||
|
@ -43,7 +44,6 @@ import { useAccess } from "../context/access/Access";
|
|||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { RolesList } from "../realm-roles/RolesList";
|
||||
import {
|
||||
convertAttributeNameToForm,
|
||||
convertFormValuesToObject,
|
||||
|
@ -70,8 +70,10 @@ import {
|
|||
toAuthorizationTab,
|
||||
} from "./routes/AuthenticationTab";
|
||||
import { ClientParams, ClientTab, toClient } from "./routes/Client";
|
||||
import { toClientRole } from "./routes/ClientRole";
|
||||
import { toClients } from "./routes/Clients";
|
||||
import { ClientScopesTab, toClientScopesTab } from "./routes/ClientScopeTab";
|
||||
import { toCreateRole } from "./routes/NewRole";
|
||||
import { ClientScopes } from "./scopes/ClientScopes";
|
||||
import { EvaluateScopes } from "./scopes/EvaluateScopes";
|
||||
import { ServiceAccount } from "./service-account/ServiceAccount";
|
||||
|
@ -474,6 +476,15 @@ export default function ClientDetails() {
|
|||
loader={loader}
|
||||
paginated={false}
|
||||
messageBundle="clients"
|
||||
toCreate={toCreateRole({ realm, clientId: client.id! })}
|
||||
toDetail={(roleId) =>
|
||||
toClientRole({
|
||||
realm,
|
||||
clientId: client.id!,
|
||||
id: roleId,
|
||||
tab: "details",
|
||||
})
|
||||
}
|
||||
isReadOnly={!(hasManageClients || client.access?.configure)}
|
||||
/>
|
||||
</Tab>
|
||||
|
|
|
@ -9,8 +9,8 @@ import { AttributeForm } from "../../components/key-value-form/AttributeForm";
|
|||
import { RoleForm } from "../../components/role-form/RoleForm";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { toClientRole } from "../../realm-roles/routes/ClientRole";
|
||||
import { toClient } from "../routes/Client";
|
||||
import { toClientRole } from "../routes/ClientRole";
|
||||
import { NewRoleParams } from "../routes/NewRole";
|
||||
|
||||
export default function CreateClientRole() {
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
import type { RouteDef } from "../route-config";
|
||||
import { AddClientRoute } from "./routes/AddClient";
|
||||
import { ClientRoute } from "./routes/Client";
|
||||
import { ClientsRoute, ClientsRouteWithTab } from "./routes/Clients";
|
||||
import { CreateInitialAccessTokenRoute } from "./routes/CreateInitialAccessToken";
|
||||
import { ImportClientRoute } from "./routes/ImportClient";
|
||||
import { MapperRoute } from "./routes/Mapper";
|
||||
import { ClientScopesRoute } from "./routes/ClientScopeTab";
|
||||
import { AuthorizationRoute } from "./routes/AuthenticationTab";
|
||||
import { NewResourceRoute } from "./routes/NewResource";
|
||||
import {
|
||||
ResourceDetailsRoute,
|
||||
ResourceDetailsWithResourceIdRoute,
|
||||
} from "./routes/Resource";
|
||||
import { NewRoleRoute } from "./routes/NewRole";
|
||||
import { NewScopeRoute } from "./routes/NewScope";
|
||||
import {
|
||||
ScopeDetailsRoute,
|
||||
ScopeDetailsWithScopeIdRoute,
|
||||
} from "./routes/Scope";
|
||||
import { NewPolicyRoute } from "./routes/NewPolicy";
|
||||
import { PolicyDetailsRoute } from "./routes/PolicyDetails";
|
||||
import {
|
||||
NewPermissionRoute,
|
||||
NewPermissionWithSelectedIdRoute,
|
||||
} from "./routes/NewPermission";
|
||||
import { PermissionDetailsRoute } from "./routes/PermissionDetails";
|
||||
import { ClientRoute } from "./routes/Client";
|
||||
import { ClientRoleRoute } from "./routes/ClientRole";
|
||||
import { ClientsRoute, ClientsRouteWithTab } from "./routes/Clients";
|
||||
import { ClientScopesRoute } from "./routes/ClientScopeTab";
|
||||
import { CreateInitialAccessTokenRoute } from "./routes/CreateInitialAccessToken";
|
||||
import {
|
||||
DedicatedScopeDetailsRoute,
|
||||
DedicatedScopeDetailsWithTabRoute,
|
||||
} from "./routes/DedicatedScopeDetails";
|
||||
import { ImportClientRoute } from "./routes/ImportClient";
|
||||
import { MapperRoute } from "./routes/Mapper";
|
||||
import {
|
||||
NewPermissionRoute,
|
||||
NewPermissionWithSelectedIdRoute,
|
||||
} from "./routes/NewPermission";
|
||||
import { NewPolicyRoute } from "./routes/NewPolicy";
|
||||
import { NewResourceRoute } from "./routes/NewResource";
|
||||
import { NewRoleRoute } from "./routes/NewRole";
|
||||
import { NewScopeRoute } from "./routes/NewScope";
|
||||
import { PermissionDetailsRoute } from "./routes/PermissionDetails";
|
||||
import { PolicyDetailsRoute } from "./routes/PolicyDetails";
|
||||
import {
|
||||
ResourceDetailsRoute,
|
||||
ResourceDetailsWithResourceIdRoute,
|
||||
} from "./routes/Resource";
|
||||
import {
|
||||
ScopeDetailsRoute,
|
||||
ScopeDetailsWithScopeIdRoute,
|
||||
} from "./routes/Scope";
|
||||
|
||||
const routes: RouteDef[] = [
|
||||
AddClientRoute,
|
||||
|
@ -41,6 +42,7 @@ const routes: RouteDef[] = [
|
|||
DedicatedScopeDetailsRoute,
|
||||
DedicatedScopeDetailsWithTabRoute,
|
||||
ClientScopesRoute,
|
||||
ClientRoleRoute,
|
||||
AuthorizationRoute,
|
||||
NewResourceRoute,
|
||||
ResourceDetailsRoute,
|
||||
|
|
|
@ -13,25 +13,16 @@ export type ClientRoleParams = {
|
|||
realm: string;
|
||||
clientId: string;
|
||||
id: string;
|
||||
tab?: ClientRoleTab;
|
||||
tab: ClientRoleTab;
|
||||
};
|
||||
|
||||
export const ClientRoleRoute: RouteDef = {
|
||||
path: "/:realm/clients/:clientId/roles/:id",
|
||||
component: lazy(() => import("../RealmRoleTabs")),
|
||||
path: "/:realm/clients/:clientId/roles/:id/:tab",
|
||||
component: lazy(() => import("../../realm-roles/RealmRoleTabs")),
|
||||
breadcrumb: (t) => t("roles:roleDetails"),
|
||||
access: "view-realm",
|
||||
};
|
||||
|
||||
export const ClientRoleRouteWithTab: RouteDef = {
|
||||
...ClientRoleRoute,
|
||||
path: "/:realm/clients/:clientId/roles/:id/:tab",
|
||||
};
|
||||
|
||||
export const toClientRole = (params: ClientRoleParams): Partial<Path> => {
|
||||
const path = params.tab ? ClientRoleRouteWithTab.path : ClientRoleRoute.path;
|
||||
|
||||
return {
|
||||
pathname: generatePath(path, params),
|
||||
};
|
||||
};
|
||||
export const toClientRole = (params: ClientRoleParams): Partial<Path> => ({
|
||||
pathname: generatePath(ClientRoleRoute.path, params),
|
||||
});
|
|
@ -1,32 +1,30 @@
|
|||
import { FunctionComponent, useState } from "react";
|
||||
import { useRouteMatch } from "react-router-dom";
|
||||
import { Link, useNavigate } from "react-router-dom-v5-compat";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AlertVariant, Button, ButtonVariant } from "@patternfly/react-core";
|
||||
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { emptyFormatter, upperCaseFormatter } from "../util";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { ClientParams, ClientRoute } from "../clients/routes/Client";
|
||||
import { toClientRole } from "./routes/ClientRole";
|
||||
import { toRealmRole } from "./routes/RealmRole";
|
||||
import { toRealmSettings } from "../realm-settings/routes/RealmSettings";
|
||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||
import { AlertVariant, Button, ButtonVariant } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, To, useNavigate } from "react-router-dom-v5-compat";
|
||||
|
||||
import "./RealmRolesSection.css";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { toRealmSettings } from "../../realm-settings/routes/RealmSettings";
|
||||
import { emptyFormatter, upperCaseFormatter } from "../../util";
|
||||
import { useAlerts } from "../alert/Alerts";
|
||||
import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import { KeycloakSpinner } from "../keycloak-spinner/KeycloakSpinner";
|
||||
import { ListEmptyState } from "../list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../table-toolbar/KeycloakDataTable";
|
||||
|
||||
import "./RolesList.css";
|
||||
|
||||
type RolesListProps = {
|
||||
paginated?: boolean;
|
||||
parentRoleId?: string;
|
||||
messageBundle?: string;
|
||||
isReadOnly: boolean;
|
||||
toCreate: To;
|
||||
toDetail: (roleId: string) => To;
|
||||
loader?: (
|
||||
first?: number,
|
||||
max?: number,
|
||||
|
@ -34,32 +32,19 @@ type RolesListProps = {
|
|||
) => Promise<RoleRepresentation[]>;
|
||||
};
|
||||
|
||||
type RoleLinkProps = {
|
||||
role: RoleRepresentation;
|
||||
};
|
||||
|
||||
const RoleLink: FunctionComponent<RoleLinkProps> = ({ children, role }) => {
|
||||
const { realm } = useRealm();
|
||||
const clientRouteMatch = useRouteMatch<ClientParams>(ClientRoute.path);
|
||||
const to = clientRouteMatch
|
||||
? toClientRole({ ...clientRouteMatch.params, id: role.id!, tab: "details" })
|
||||
: toRealmRole({ realm, id: role.id!, tab: "details" });
|
||||
|
||||
return <Link to={to}>{children}</Link>;
|
||||
};
|
||||
|
||||
export const RolesList = ({
|
||||
loader,
|
||||
paginated = true,
|
||||
parentRoleId,
|
||||
messageBundle = "roles",
|
||||
toCreate,
|
||||
toDetail,
|
||||
isReadOnly,
|
||||
}: RolesListProps) => {
|
||||
const { t } = useTranslation(messageBundle);
|
||||
const navigate = useNavigate();
|
||||
const { adminClient } = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const { url } = useRouteMatch();
|
||||
const { realm: realmName } = useRealm();
|
||||
const [realm, setRealm] = useState<RealmRepresentation>();
|
||||
|
||||
|
@ -75,7 +60,7 @@ export const RolesList = ({
|
|||
|
||||
const RoleDetailLink = (role: RoleRepresentation) =>
|
||||
role.name !== realm?.defaultRole?.name ? (
|
||||
<RoleLink role={role}>{role.name}</RoleLink>
|
||||
<Link to={toDetail(role.id!)}>{role.name}</Link>
|
||||
) : (
|
||||
<>
|
||||
<Link
|
||||
|
@ -116,8 +101,6 @@ export const RolesList = ({
|
|||
},
|
||||
});
|
||||
|
||||
const goToCreate = () => navigate(`${url}/new`);
|
||||
|
||||
if (!realm) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
|
@ -133,7 +116,10 @@ export const RolesList = ({
|
|||
isPaginated={paginated}
|
||||
toolbarItem={
|
||||
!isReadOnly && (
|
||||
<Button data-testid="create-role" onClick={goToCreate}>
|
||||
<Button
|
||||
data-testid="create-role"
|
||||
component={(props) => <Link {...props} to={toCreate} />}
|
||||
>
|
||||
{t("createRole")}
|
||||
</Button>
|
||||
)
|
||||
|
@ -179,7 +165,7 @@ export const RolesList = ({
|
|||
message={t("noRoles")}
|
||||
instructions={isReadOnly ? "" : t("noRolesInstructions")}
|
||||
primaryActionText={isReadOnly ? "" : t("createRole")}
|
||||
onPrimaryAction={goToCreate}
|
||||
onPrimaryAction={() => navigate(toCreate)}
|
||||
/>
|
||||
}
|
||||
/>
|
|
@ -92,7 +92,7 @@ const createLink = (realm: string, event: AdminEventRepresentation) => {
|
|||
}
|
||||
|
||||
if (event.resourcePath?.startsWith("roles-by-id")) {
|
||||
return toRealmRole({ realm, id });
|
||||
return toRealmRole({ realm, id, tab: "details" });
|
||||
}
|
||||
|
||||
return "";
|
||||
|
|
|
@ -16,6 +16,11 @@ import { useRouteMatch } from "react-router-dom";
|
|||
import { useNavigate } from "react-router-dom-v5-compat";
|
||||
|
||||
import { toClient } from "../clients/routes/Client";
|
||||
import {
|
||||
ClientRoleParams,
|
||||
ClientRoleRoute,
|
||||
toClientRole,
|
||||
} from "../clients/routes/ClientRole";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import {
|
||||
|
@ -37,11 +42,6 @@ import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
|||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { useParams } from "../utils/useParams";
|
||||
import {
|
||||
ClientRoleParams,
|
||||
ClientRoleRoute,
|
||||
toClientRole,
|
||||
} from "./routes/ClientRole";
|
||||
import { toRealmRole } from "./routes/RealmRole";
|
||||
import { toRealmRoles } from "./routes/RealmRoles";
|
||||
import { UsersInRoleTab } from "./UsersInRoleTab";
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import { PageSection } from "@patternfly/react-core";
|
||||
|
||||
import { RolesList } from "../components/roles-list/RolesList";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { RolesList } from "./RolesList";
|
||||
import helpUrls from "../help-urls";
|
||||
import { useAccess } from "../context/access/Access";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import helpUrls from "../help-urls";
|
||||
import { toAddRole } from "./routes/AddRole";
|
||||
import { toRealmRole } from "./routes/RealmRole";
|
||||
|
||||
export default function RealmRolesSection() {
|
||||
const { adminClient } = useAdminClient();
|
||||
|
||||
const { realm } = useRealm();
|
||||
const { hasAccess } = useAccess();
|
||||
const isManager = hasAccess("manage-realm");
|
||||
|
||||
|
@ -34,7 +38,14 @@ export default function RealmRolesSection() {
|
|||
helpUrl={helpUrls.realmRolesUrl}
|
||||
/>
|
||||
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
||||
<RolesList loader={loader} isReadOnly={!isManager} />
|
||||
<RolesList
|
||||
loader={loader}
|
||||
toCreate={toAddRole({ realm })}
|
||||
toDetail={(roleId) =>
|
||||
toRealmRole({ realm, id: roleId, tab: "details" })
|
||||
}
|
||||
isReadOnly={!isManager}
|
||||
/>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -3,6 +3,7 @@ import { QuestionCircleIcon } from "@patternfly/react-icons";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom-v5-compat";
|
||||
|
||||
import type { ClientRoleParams } from "../clients/routes/ClientRole";
|
||||
import { useHelp } from "../components/help-enabler/HelpHeader";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
|
@ -10,7 +11,6 @@ import { useAdminClient } from "../context/auth/AdminClient";
|
|||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { emptyFormatter, upperCaseFormatter } from "../util";
|
||||
import { useParams } from "../utils/useParams";
|
||||
import type { ClientRoleParams } from "./routes/ClientRole";
|
||||
|
||||
export const UsersInRoleTab = () => {
|
||||
const navigate = useNavigate();
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
import type { RouteDef } from "../route-config";
|
||||
import { AddRoleRoute } from "./routes/AddRole";
|
||||
import { ClientRoleRoute, ClientRoleRouteWithTab } from "./routes/ClientRole";
|
||||
import { RealmRoleRoute, RealmRoleRouteWithTab } from "./routes/RealmRole";
|
||||
import { RealmRoleRoute } from "./routes/RealmRole";
|
||||
import { RealmRolesRoute } from "./routes/RealmRoles";
|
||||
|
||||
const routes: RouteDef[] = [
|
||||
ClientRoleRoute,
|
||||
ClientRoleRouteWithTab,
|
||||
RealmRolesRoute,
|
||||
AddRoleRoute,
|
||||
RealmRoleRoute,
|
||||
RealmRoleRouteWithTab,
|
||||
];
|
||||
const routes: RouteDef[] = [RealmRolesRoute, AddRoleRoute, RealmRoleRoute];
|
||||
|
||||
export default routes;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { lazy } from "react";
|
||||
import type { Path } from "react-router-dom-v5-compat";
|
||||
import { generatePath } from "react-router-dom-v5-compat";
|
||||
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type RealmRoleTab =
|
||||
|
@ -12,25 +13,16 @@ export type RealmRoleTab =
|
|||
export type RealmRoleParams = {
|
||||
realm: string;
|
||||
id: string;
|
||||
tab?: RealmRoleTab;
|
||||
tab: RealmRoleTab;
|
||||
};
|
||||
|
||||
export const RealmRoleRoute: RouteDef = {
|
||||
path: "/:realm/roles/:id",
|
||||
path: "/:realm/roles/:id/:tab",
|
||||
component: lazy(() => import("../RealmRoleTabs")),
|
||||
breadcrumb: (t) => t("roles:roleDetails"),
|
||||
access: ["view-realm", "view-users"],
|
||||
};
|
||||
|
||||
export const RealmRoleRouteWithTab: RouteDef = {
|
||||
...RealmRoleRoute,
|
||||
path: "/:realm/roles/:id/:tab",
|
||||
};
|
||||
|
||||
export const toRealmRole = (params: RealmRoleParams): Partial<Path> => {
|
||||
const path = params.tab ? RealmRoleRouteWithTab.path : RealmRoleRoute.path;
|
||||
|
||||
return {
|
||||
pathname: generatePath(path, params),
|
||||
};
|
||||
};
|
||||
export const toRealmRole = (params: RealmRoleParams): Partial<Path> => ({
|
||||
pathname: generatePath(RealmRoleRoute.path, params),
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue