Make 'User Profile' tabs routable (#1862)
This commit is contained in:
parent
b2b61c26ef
commit
884102d83b
4 changed files with 60 additions and 12 deletions
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
24
src/realm-settings/routes/UserProfile.ts
Normal file
24
src/realm-settings/routes/UserProfile.ts
Normal 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),
|
||||
});
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue