f088b0009c
* initial screen Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * more screens Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added members tab Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added the backend Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added member add / invite models Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * initial version of the identity provider section Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * add link and unlink providers Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * small fix Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * PR comments Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Do not validate broker domain when the domain is an empty string Closes #29759 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added filter and value Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added first name last name Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * refresh menu when realm organization is changed Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * changed to record Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * changed to form data Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * fixed lint error Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Changing name of invitation parameters Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Chancing name of parameters on the client Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Enable organization at the realm before running tests Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Domain help message Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Handling model validation errors when creating organizations Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Message key for organizationDetails Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Do not change kc.org attribute on group Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * add realm into the context Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * tests Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Changing button in invitation model to use Send instead of Save Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Better message when validating the organization domain Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Fixing compilation error after rebase Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * fixed test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * removed wait as it no longer required and skip flacky test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * skip tests that are flaky Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * stabilize user create test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> --------- Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Co-authored-by: Pedro Igor <pigor.craveiro@gmail.com>
146 lines
4.5 KiB
TypeScript
146 lines
4.5 KiB
TypeScript
import {
|
|
Divider,
|
|
Nav,
|
|
NavGroup,
|
|
NavItem,
|
|
NavList,
|
|
PageSidebar,
|
|
PageSidebarBody,
|
|
} from "@patternfly/react-core";
|
|
import { FormEvent } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { NavLink, useMatch, useNavigate } from "react-router-dom";
|
|
import { RealmSelector } from "./components/realm-selector/RealmSelector";
|
|
import { useAccess } from "./context/access/Access";
|
|
import { useRealm } from "./context/realm-context/RealmContext";
|
|
import { useServerInfo } from "./context/server-info/ServerInfoProvider";
|
|
import { toPage } from "./page/routes";
|
|
import { AddRealmRoute } from "./realm/routes/AddRealm";
|
|
import { routes } from "./routes";
|
|
import useIsFeatureEnabled, { Feature } from "./utils/useIsFeatureEnabled";
|
|
|
|
import "./page-nav.css";
|
|
|
|
type LeftNavProps = { title: string; path: string; id?: string };
|
|
|
|
const LeftNav = ({ title, path, id }: LeftNavProps) => {
|
|
const { t } = useTranslation();
|
|
const { hasAccess } = useAccess();
|
|
const { realm } = useRealm();
|
|
const encodedRealm = encodeURIComponent(realm);
|
|
const route = routes.find(
|
|
(route) =>
|
|
route.path.replace(/\/:.+?(\?|(?:(?!\/).)*|$)/g, "") === (id || path),
|
|
);
|
|
|
|
const accessAllowed =
|
|
route &&
|
|
(route.handle.access instanceof Array
|
|
? hasAccess(...route.handle.access)
|
|
: hasAccess(route.handle.access));
|
|
|
|
if (!accessAllowed) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<li>
|
|
<NavLink
|
|
id={"nav-item" + path.replace("/", "-")}
|
|
to={`/${encodedRealm}${path}`}
|
|
className={({ isActive }) =>
|
|
`pf-v5-c-nav__link${isActive ? " pf-m-current" : ""}`
|
|
}
|
|
>
|
|
{t(title)}
|
|
</NavLink>
|
|
</li>
|
|
);
|
|
};
|
|
|
|
export const PageNav = () => {
|
|
const { t } = useTranslation();
|
|
const { hasSomeAccess } = useAccess();
|
|
const { componentTypes } = useServerInfo();
|
|
const isFeatureEnabled = useIsFeatureEnabled();
|
|
const pages =
|
|
componentTypes?.["org.keycloak.services.ui.extend.UiPageProvider"];
|
|
const navigate = useNavigate();
|
|
const { realmRepresentation } = useRealm();
|
|
|
|
type SelectedItem = {
|
|
groupId: number | string;
|
|
itemId: number | string;
|
|
to: string;
|
|
event: FormEvent<HTMLInputElement>;
|
|
};
|
|
|
|
const onSelect = (item: SelectedItem) => {
|
|
navigate(item.to);
|
|
item.event.preventDefault();
|
|
};
|
|
|
|
const showManage = hasSomeAccess(
|
|
"view-realm",
|
|
"query-groups",
|
|
"query-users",
|
|
"query-clients",
|
|
"view-events",
|
|
);
|
|
|
|
const showConfigure = hasSomeAccess(
|
|
"view-realm",
|
|
"query-clients",
|
|
"view-identity-providers",
|
|
);
|
|
|
|
const isOnAddRealm = !!useMatch(AddRealmRoute.path);
|
|
|
|
return (
|
|
<PageSidebar className="keycloak__page_nav__nav">
|
|
<PageSidebarBody>
|
|
<Nav onSelect={(_event, item) => onSelect(item as SelectedItem)}>
|
|
<NavList>
|
|
<NavItem className="keycloak__page_nav__nav_item__realm-selector">
|
|
<RealmSelector />
|
|
</NavItem>
|
|
</NavList>
|
|
<Divider />
|
|
{showManage && !isOnAddRealm && (
|
|
<NavGroup aria-label={t("manage")} title={t("manage")}>
|
|
{isFeatureEnabled(Feature.Organizations) &&
|
|
realmRepresentation?.organizationsEnabled && (
|
|
<LeftNav title="organizations" path="/organizations" />
|
|
)}
|
|
<LeftNav title="clients" path="/clients" />
|
|
<LeftNav title="clientScopes" path="/client-scopes" />
|
|
<LeftNav title="realmRoles" path="/roles" />
|
|
<LeftNav title="users" path="/users" />
|
|
<LeftNav title="groups" path="/groups" />
|
|
<LeftNav title="sessions" path="/sessions" />
|
|
<LeftNav title="events" path="/events" />
|
|
</NavGroup>
|
|
)}
|
|
|
|
{showConfigure && !isOnAddRealm && (
|
|
<NavGroup aria-label={t("configure")} title={t("configure")}>
|
|
<LeftNav title="realmSettings" path="/realm-settings" />
|
|
<LeftNav title="authentication" path="/authentication" />
|
|
<LeftNav title="identityProviders" path="/identity-providers" />
|
|
<LeftNav title="userFederation" path="/user-federation" />
|
|
{isFeatureEnabled(Feature.DeclarativeUI) &&
|
|
pages?.map((p) => (
|
|
<LeftNav
|
|
key={p.id}
|
|
title={p.id}
|
|
path={toPage({ providerId: p.id }).pathname!}
|
|
id="/page-section"
|
|
/>
|
|
))}
|
|
</NavGroup>
|
|
)}
|
|
</Nav>
|
|
</PageSidebarBody>
|
|
</PageSidebar>
|
|
);
|
|
};
|