Make 'User Profile' tabs routable (#1862)

This commit is contained in:
Jon Koops 2022-01-19 10:41:52 +01:00 committed by GitHub
parent b2b61c26ef
commit 884102d83b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 12 deletions

View file

@ -13,17 +13,23 @@ import React, {
} from "react";
import { useLocation } from "react-router-dom";
// TODO: Remove the custom 'children' props and type once the following issue has been resolved:
// https://github.com/patternfly/patternfly-react/issues/6766
type ChildElement = ReactElement<TabProps, JSXElementConstructor<TabProps>>;
type Child = ChildElement | boolean | null | undefined;
// TODO: Figure out why we need to omit 'ref' from the props.
type RoutableTabsProps = { children: Child | Child[] } & Omit<
type RoutableTabsProps = {
children: Child | Child[];
defaultLocation?: LocationDescriptorObject;
} & Omit<
TabsProps,
"ref" | "activeKey" | "component" | "children"
"ref" | "activeKey" | "defaultActiveKey" | "component" | "children"
>;
export const RoutableTabs = ({
children,
defaultLocation,
...otherProps
}: RoutableTabsProps) => {
const { pathname } = useLocation();
@ -44,7 +50,9 @@ export const RoutableTabs = ({
return (
<Tabs
activeKey={exactMatch ?? nearestMatch ?? pathname}
activeKey={
exactMatch ?? nearestMatch ?? defaultLocation?.pathname ?? pathname
}
component={TabsComponent.nav}
inset={{
default: "insetNone",

View file

@ -15,6 +15,7 @@ import { AddClientPolicyRoute } from "./routes/AddClientPolicy";
import { EditClientPolicyRoute } from "./routes/EditClientPolicy";
import { NewClientPolicyConditionRoute } from "./routes/AddCondition";
import { EditClientPolicyConditionRoute } from "./routes/EditCondition";
import { UserProfileRoute } from "./routes/UserProfile";
const routes: RouteDef[] = [
RealmSettingsRoute,
@ -33,6 +34,7 @@ const routes: RouteDef[] = [
EditClientPolicyRoute,
NewClientPolicyConditionRoute,
EditClientPolicyConditionRoute,
UserProfileRoute,
];
export default routes;

View file

@ -0,0 +1,24 @@
import type { LocationDescriptorObject } from "history";
import { lazy } from "react";
import { generatePath } from "react-router-dom";
import type { RouteDef } from "../../route-config";
export type UserProfileTab = "attributes" | "attributesGroup" | "jsonEditor";
export type UserProfileParams = {
realm: string;
tab: UserProfileTab;
};
export const UserProfileRoute: RouteDef = {
path: "/:realm/realm-settings/userProfile/:tab",
component: lazy(() => import("../RealmSettingsSection")),
breadcrumb: (t) => t("realmSettings"),
access: "view-realm",
};
export const toUserProfile = (
params: UserProfileParams
): LocationDescriptorObject => ({
pathname: generatePath(UserProfileRoute.path, params),
});

View file

@ -1,10 +1,16 @@
import type UserProfileConfig from "@keycloak/keycloak-admin-client/lib/defs/userProfileConfig";
import { AlertVariant, Tab, Tabs, TabTitleText } from "@patternfly/react-core";
import { AlertVariant, Tab, TabTitleText } from "@patternfly/react-core";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
import { useAlerts } from "../../components/alert/Alerts";
import {
routableTab,
RoutableTabs,
} from "../../components/routable-tabs/RoutableTabs";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useRealm } from "../../context/realm-context/RealmContext";
import { toUserProfile } from "../routes/UserProfile";
import { AttributesGroupTab } from "./AttributesGroupTab";
import { JsonEditorTab } from "./JsonEditorTab";
@ -22,8 +28,8 @@ export const UserProfileTab = () => {
const adminClient = useAdminClient();
const { realm } = useRealm();
const { t } = useTranslation("realm-settings");
const history = useHistory();
const { addAlert, addError } = useAlerts();
const [activeTab, setActiveTab] = useState("attributes");
const [config, setConfig] = useState<UserProfileConfig>();
const [isSaving, setIsSaving] = useState(false);
const [refreshCount, setRefreshCount] = useState(0);
@ -62,28 +68,36 @@ export const UserProfileTab = () => {
};
return (
<Tabs
activeKey={activeTab}
onSelect={(_, key) => setActiveTab(key.toString())}
<RoutableTabs
defaultLocation={toUserProfile({ realm, tab: "attributes" })}
mountOnEnter
>
<Tab
eventKey="attributes"
title={<TabTitleText>{t("attributes")}</TabTitleText>}
{...routableTab({
to: toUserProfile({ realm, tab: "attributes" }),
history,
})}
></Tab>
<Tab
eventKey="attributesGroup"
title={<TabTitleText>{t("attributesGroup")}</TabTitleText>}
data-testid="attributesGroupTab"
{...routableTab({
to: toUserProfile({ realm, tab: "attributesGroup" }),
history,
})}
>
<AttributesGroupTab config={config} onSave={onSave} />
</Tab>
<Tab
eventKey="jsonEditor"
title={<TabTitleText>{t("jsonEditor")}</TabTitleText>}
{...routableTab({
to: toUserProfile({ realm, tab: "jsonEditor" }),
history,
})}
>
<JsonEditorTab config={config} onSave={onSave} isSaving={isSaving} />
</Tab>
</Tabs>
</RoutableTabs>
);
};