Sub group navigation in groups section (#274)
* list sub group of a group using the id * introduced group bread crumb component to render this builds up the groups as you click to subgroups * added deeplinking * fixed route config types * fixed new realm prefix * added null checks for if group not found * changed labes to groups
This commit is contained in:
parent
bbfccea940
commit
ce0ce6d59e
8 changed files with 345 additions and 77 deletions
11
src/App.tsx
11
src/App.tsx
|
@ -18,6 +18,7 @@ import { AccessContextProvider, useAccess } from "./context/access/Access";
|
||||||
import { routes, RouteDef } from "./route-config";
|
import { routes, RouteDef } from "./route-config";
|
||||||
import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
|
import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
|
||||||
import { ForbiddenSection } from "./ForbiddenSection";
|
import { ForbiddenSection } from "./ForbiddenSection";
|
||||||
|
import { SubGroups } from "./groups/GroupsSection";
|
||||||
import { useRealm } from "./context/realm-context/RealmContext";
|
import { useRealm } from "./context/realm-context/RealmContext";
|
||||||
import { useAdminClient, asyncStateFetch } from "./context/auth/AdminClient";
|
import { useAdminClient, asyncStateFetch } from "./context/auth/AdminClient";
|
||||||
|
|
||||||
|
@ -28,7 +29,9 @@ const AppContexts = ({ children }: { children: ReactNode }) => (
|
||||||
<AccessContextProvider>
|
<AccessContextProvider>
|
||||||
<Help>
|
<Help>
|
||||||
<AlertProvider>
|
<AlertProvider>
|
||||||
<ServerInfoProvider>{children}</ServerInfoProvider>
|
<ServerInfoProvider>
|
||||||
|
<SubGroups>{children}</SubGroups>
|
||||||
|
</ServerInfoProvider>
|
||||||
</AlertProvider>
|
</AlertProvider>
|
||||||
</Help>
|
</Help>
|
||||||
</AccessContextProvider>
|
</AccessContextProvider>
|
||||||
|
@ -79,7 +82,11 @@ export const App = () => {
|
||||||
<Switch>
|
<Switch>
|
||||||
{routes(() => {}).map((route, i) => (
|
{routes(() => {}).map((route, i) => (
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact={
|
||||||
|
route.matchOptions?.exact === undefined
|
||||||
|
? true
|
||||||
|
: route.matchOptions.exact
|
||||||
|
}
|
||||||
key={i}
|
key={i}
|
||||||
path={route.path}
|
path={route.path}
|
||||||
component={() => (
|
component={() => (
|
||||||
|
|
51
src/components/bread-crumb/GroupBreadCrumbs.tsx
Normal file
51
src/components/bread-crumb/GroupBreadCrumbs.tsx
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { Link, useHistory } from "react-router-dom";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Breadcrumb, BreadcrumbItem } from "@patternfly/react-core";
|
||||||
|
|
||||||
|
import { useSubGroups } from "../../groups/GroupsSection";
|
||||||
|
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||||
|
|
||||||
|
export const GroupBreadCrumbs = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { clear, remove, subGroups } = useSubGroups();
|
||||||
|
const { realm } = useRealm();
|
||||||
|
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return history.listen(({ pathname }) => {
|
||||||
|
if (pathname.indexOf("/groups") === -1 || pathname.endsWith("/groups")) {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [history]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{subGroups.length !== 0 && (
|
||||||
|
<Breadcrumb>
|
||||||
|
<BreadcrumbItem key="home">
|
||||||
|
<Link to={`/${realm}/groups`}>{t("groups")}</Link>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
{subGroups.map((group, i) => (
|
||||||
|
<BreadcrumbItem key={i} isActive={subGroups.length - 1 === i}>
|
||||||
|
{subGroups.length - 1 !== i && (
|
||||||
|
<Link
|
||||||
|
to={location.pathname.substr(
|
||||||
|
0,
|
||||||
|
location.pathname.indexOf(group.id!) + group.id!.length
|
||||||
|
)}
|
||||||
|
onClick={() => remove(group)}
|
||||||
|
>
|
||||||
|
{group.name}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
{subGroups.length - 1 === i && <>{group.name}</>}
|
||||||
|
</BreadcrumbItem>
|
||||||
|
))}
|
||||||
|
</Breadcrumb>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -6,6 +6,7 @@ import { Breadcrumb, BreadcrumbItem } from "@patternfly/react-core";
|
||||||
|
|
||||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||||
import { routes } from "../../route-config";
|
import { routes } from "../../route-config";
|
||||||
|
import { GroupBreadCrumbs } from "./GroupBreadCrumbs";
|
||||||
|
|
||||||
export const PageBreadCrumbs = () => {
|
export const PageBreadCrumbs = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -25,6 +26,7 @@ export const PageBreadCrumbs = () => {
|
||||||
))}
|
))}
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
)}
|
)}
|
||||||
|
<GroupBreadCrumbs />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { mount } from "enzyme";
|
||||||
|
import { MemoryRouter } from "react-router-dom";
|
||||||
|
|
||||||
|
import { GroupBreadCrumbs } from "../GroupBreadCrumbs";
|
||||||
|
import { SubGroups, useSubGroups } from "../../../groups/GroupsSection";
|
||||||
|
|
||||||
|
const GroupCrumbs = () => {
|
||||||
|
const { setSubGroups } = useSubGroups();
|
||||||
|
useEffect(() => {
|
||||||
|
setSubGroups([
|
||||||
|
{ id: "1", name: "first group" },
|
||||||
|
{ id: "123", name: "active group" },
|
||||||
|
]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <GroupBreadCrumbs />;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Group BreadCrumbs tests", () => {
|
||||||
|
it("couple of crumbs", () => {
|
||||||
|
const crumbs = mount(
|
||||||
|
<MemoryRouter initialEntries={["/groups"]}>
|
||||||
|
<SubGroups>
|
||||||
|
<GroupCrumbs />
|
||||||
|
</SubGroups>
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(crumbs.find(GroupCrumbs)).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,140 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Group BreadCrumbs tests couple of crumbs 1`] = `
|
||||||
|
<GroupCrumbs>
|
||||||
|
<GroupBreadCrumbs>
|
||||||
|
<Breadcrumb>
|
||||||
|
<nav
|
||||||
|
aria-label="Breadcrumb"
|
||||||
|
className="pf-c-breadcrumb"
|
||||||
|
data-ouia-component-id="OUIA-Generated-Breadcrumb-1"
|
||||||
|
data-ouia-component-type="PF4/Breadcrumb"
|
||||||
|
data-ouia-safe={true}
|
||||||
|
>
|
||||||
|
<ol
|
||||||
|
className="pf-c-breadcrumb__list"
|
||||||
|
>
|
||||||
|
<BreadcrumbItem
|
||||||
|
key=".$home"
|
||||||
|
showDivider={false}
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
className="pf-c-breadcrumb__item"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
to="//groups"
|
||||||
|
>
|
||||||
|
<LinkAnchor
|
||||||
|
href="//groups"
|
||||||
|
navigate={[Function]}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="//groups"
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
groups
|
||||||
|
</a>
|
||||||
|
</LinkAnchor>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
<BreadcrumbItem
|
||||||
|
isActive={false}
|
||||||
|
key=".1:$0"
|
||||||
|
showDivider={true}
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
className="pf-c-breadcrumb__item"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="pf-c-breadcrumb__item-divider"
|
||||||
|
>
|
||||||
|
<AngleRightIcon
|
||||||
|
color="currentColor"
|
||||||
|
noVerticalAlign={false}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden={true}
|
||||||
|
aria-labelledby={null}
|
||||||
|
fill="currentColor"
|
||||||
|
height="1em"
|
||||||
|
role="img"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"verticalAlign": "-0.125em",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewBox="0 0 256 512"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</AngleRightIcon>
|
||||||
|
</span>
|
||||||
|
<Link
|
||||||
|
onClick={[Function]}
|
||||||
|
to=""
|
||||||
|
>
|
||||||
|
<LinkAnchor
|
||||||
|
href="/"
|
||||||
|
navigate={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="/"
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
first group
|
||||||
|
</a>
|
||||||
|
</LinkAnchor>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
<BreadcrumbItem
|
||||||
|
isActive={true}
|
||||||
|
key=".1:$1"
|
||||||
|
showDivider={true}
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
className="pf-c-breadcrumb__item"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="pf-c-breadcrumb__item-divider"
|
||||||
|
>
|
||||||
|
<AngleRightIcon
|
||||||
|
color="currentColor"
|
||||||
|
noVerticalAlign={false}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden={true}
|
||||||
|
aria-labelledby={null}
|
||||||
|
fill="currentColor"
|
||||||
|
height="1em"
|
||||||
|
role="img"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"verticalAlign": "-0.125em",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewBox="0 0 256 512"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</AngleRightIcon>
|
||||||
|
</span>
|
||||||
|
active group
|
||||||
|
</li>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</Breadcrumb>
|
||||||
|
</GroupBreadCrumbs>
|
||||||
|
</GroupCrumbs>
|
||||||
|
`;
|
|
@ -21,63 +21,6 @@ exports[`BreadCrumbs tests couple of crumbs 1`] = `
|
||||||
<li
|
<li
|
||||||
className="pf-c-breadcrumb__item"
|
className="pf-c-breadcrumb__item"
|
||||||
>
|
>
|
||||||
<Link
|
|
||||||
to="/master"
|
|
||||||
>
|
|
||||||
<LinkAnchor
|
|
||||||
href="/master"
|
|
||||||
navigate={[Function]}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="/master"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
key="/master"
|
|
||||||
>
|
|
||||||
Home
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</LinkAnchor>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</BreadcrumbItem>
|
|
||||||
<BreadcrumbItem
|
|
||||||
isActive={false}
|
|
||||||
key=".$1"
|
|
||||||
showDivider={true}
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="pf-c-breadcrumb__item"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="pf-c-breadcrumb__item-divider"
|
|
||||||
>
|
|
||||||
<AngleRightIcon
|
|
||||||
color="currentColor"
|
|
||||||
noVerticalAlign={false}
|
|
||||||
size="sm"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
aria-labelledby={null}
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
role="img"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"verticalAlign": "-0.125em",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewBox="0 0 256 512"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</AngleRightIcon>
|
|
||||||
</span>
|
|
||||||
<Link
|
<Link
|
||||||
to="/master/clients"
|
to="/master/clients"
|
||||||
>
|
>
|
||||||
|
@ -101,7 +44,7 @@ exports[`BreadCrumbs tests couple of crumbs 1`] = `
|
||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
<BreadcrumbItem
|
<BreadcrumbItem
|
||||||
isActive={true}
|
isActive={true}
|
||||||
key=".$2"
|
key=".$1"
|
||||||
showDivider={true}
|
showDivider={true}
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
|
@ -145,5 +88,6 @@ exports[`BreadCrumbs tests couple of crumbs 1`] = `
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
|
<GroupBreadCrumbs />
|
||||||
</PageBreadCrumbs>
|
</PageBreadCrumbs>
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
import React, { useState } from "react";
|
import React, {
|
||||||
|
createContext,
|
||||||
|
ReactNode,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
@ -21,12 +28,58 @@ import { useAlerts } from "../components/alert/Alerts";
|
||||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||||
|
|
||||||
import "./GroupsSection.css";
|
import "./GroupsSection.css";
|
||||||
import { Link, useRouteMatch } from "react-router-dom";
|
import { useRealm } from "../context/realm-context/RealmContext";
|
||||||
|
|
||||||
type GroupTableData = GroupRepresentation & {
|
type GroupTableData = GroupRepresentation & {
|
||||||
membersLength?: number;
|
membersLength?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type SubGroupsProps = {
|
||||||
|
subGroups: GroupRepresentation[];
|
||||||
|
setSubGroups: (group: GroupRepresentation[]) => void;
|
||||||
|
clear: () => void;
|
||||||
|
remove: (group: GroupRepresentation) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGroupContext = createContext<SubGroupsProps>({
|
||||||
|
subGroups: [],
|
||||||
|
setSubGroups: () => {},
|
||||||
|
clear: () => {},
|
||||||
|
remove: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const SubGroups = ({ children }: { children: ReactNode }) => {
|
||||||
|
const [subGroups, setSubGroups] = useState<GroupRepresentation[]>([]);
|
||||||
|
|
||||||
|
const clear = () => setSubGroups([]);
|
||||||
|
const remove = (group: GroupRepresentation) =>
|
||||||
|
setSubGroups(
|
||||||
|
subGroups.slice(
|
||||||
|
0,
|
||||||
|
subGroups.findIndex((g) => g.id === group.id)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<SubGroupContext.Provider
|
||||||
|
value={{ subGroups, setSubGroups, clear, remove }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</SubGroupContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSubGroups = () => useContext(SubGroupContext);
|
||||||
|
|
||||||
|
const getId = (pathname: string) => {
|
||||||
|
const pathParts = pathname.substr(1).split("/");
|
||||||
|
return pathParts.length > 1 ? pathParts.splice(2) : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getLastId = (pathname: string) => {
|
||||||
|
const pathParts = getId(pathname);
|
||||||
|
return pathParts ? pathParts[pathParts.length - 1] : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export const GroupsSection = () => {
|
export const GroupsSection = () => {
|
||||||
const { t } = useTranslation("groups");
|
const { t } = useTranslation("groups");
|
||||||
const adminClient = useAdminClient();
|
const adminClient = useAdminClient();
|
||||||
|
@ -34,8 +87,14 @@ export const GroupsSection = () => {
|
||||||
const [createGroupName, setCreateGroupName] = useState("");
|
const [createGroupName, setCreateGroupName] = useState("");
|
||||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
const [selectedRows, setSelectedRows] = useState<GroupRepresentation[]>([]);
|
const [selectedRows, setSelectedRows] = useState<GroupRepresentation[]>([]);
|
||||||
|
const { subGroups, setSubGroups } = useSubGroups();
|
||||||
const { addAlert } = useAlerts();
|
const { addAlert } = useAlerts();
|
||||||
const { url } = useRouteMatch();
|
const { realm } = useRealm();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const location = useLocation();
|
||||||
|
const id = getLastId(location.pathname);
|
||||||
|
|
||||||
const [key, setKey] = useState("");
|
const [key, setKey] = useState("");
|
||||||
const refresh = () => setKey(`${new Date().getTime()}`);
|
const refresh = () => setKey(`${new Date().getTime()}`);
|
||||||
|
|
||||||
|
@ -45,17 +104,47 @@ export const GroupsSection = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const loader = async () => {
|
const loader = async () => {
|
||||||
const groupsData = await adminClient.groups.find();
|
let groupsData;
|
||||||
|
if (!id) {
|
||||||
|
groupsData = await adminClient.groups.find();
|
||||||
|
} else {
|
||||||
|
const ids = getId(location.pathname);
|
||||||
|
const isNavigationStateInValid = ids && ids.length !== subGroups.length;
|
||||||
|
if (isNavigationStateInValid) {
|
||||||
|
const groups = [];
|
||||||
|
for (const i of ids!) {
|
||||||
|
const group = await adminClient.groups.findOne({ id: i });
|
||||||
|
if (group) groups.push(group);
|
||||||
|
}
|
||||||
|
setSubGroups(groups);
|
||||||
|
groupsData = groups.pop()?.subGroups!;
|
||||||
|
} else {
|
||||||
|
const group = await adminClient.groups.findOne({ id });
|
||||||
|
if (group) {
|
||||||
|
setSubGroups([...subGroups, group]);
|
||||||
|
groupsData = group.subGroups!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupsData) {
|
||||||
const memberPromises = groupsData.map((group) => getMembers(group.id!));
|
const memberPromises = groupsData.map((group) => getMembers(group.id!));
|
||||||
const memberData = await Promise.all(memberPromises);
|
const memberData = await Promise.all(memberPromises);
|
||||||
const updatedObject = groupsData.map((group: GroupTableData, i) => {
|
return groupsData.map((group: GroupTableData, i) => {
|
||||||
group.membersLength = memberData[i];
|
group.membersLength = memberData[i];
|
||||||
return group;
|
return group;
|
||||||
});
|
});
|
||||||
return updatedObject;
|
} else {
|
||||||
|
history.push(`/${realm}/groups`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
refresh();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
const handleModalToggle = () => {
|
const handleModalToggle = () => {
|
||||||
setIsCreateModalOpen(!isCreateModalOpen);
|
setIsCreateModalOpen(!isCreateModalOpen);
|
||||||
};
|
};
|
||||||
|
@ -85,7 +174,7 @@ export const GroupsSection = () => {
|
||||||
|
|
||||||
const GroupNameCell = (group: GroupTableData) => (
|
const GroupNameCell = (group: GroupTableData) => (
|
||||||
<>
|
<>
|
||||||
<Link key={group.id} to={`${url}/${group.id}`}>
|
<Link key={group.id} to={`${location.pathname}/${group.id}`}>
|
||||||
{group.name}
|
{group.name}
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
|
@ -107,8 +196,8 @@ export const GroupsSection = () => {
|
||||||
onSelect={(rows) => setSelectedRows([...rows])}
|
onSelect={(rows) => setSelectedRows([...rows])}
|
||||||
canSelectAll={false}
|
canSelectAll={false}
|
||||||
loader={loader}
|
loader={loader}
|
||||||
ariaLabelKey="client-scopes:clientScopeList"
|
ariaLabelKey="groups:groups"
|
||||||
searchPlaceholderKey="client-scopes:searchFor"
|
searchPlaceholderKey="groups:searchForGroups"
|
||||||
toolbarItem={
|
toolbarItem={
|
||||||
<>
|
<>
|
||||||
<ToolbarItem>
|
<ToolbarItem>
|
||||||
|
|
|
@ -26,13 +26,13 @@ import { BreadcrumbsRoute } from "use-react-router-breadcrumbs";
|
||||||
import { RealmRoleTabs } from "./realm-roles/RealmRoleTabs";
|
import { RealmRoleTabs } from "./realm-roles/RealmRoleTabs";
|
||||||
|
|
||||||
export type RouteDef = BreadcrumbsRoute & {
|
export type RouteDef = BreadcrumbsRoute & {
|
||||||
component: () => JSX.Element;
|
|
||||||
access: AccessType;
|
access: AccessType;
|
||||||
|
component: () => JSX.Element;
|
||||||
};
|
};
|
||||||
|
|
||||||
type RoutesFn = (t: TFunction) => RouteDef[];
|
type RoutesFn = (t: TFunction) => RouteDef[];
|
||||||
|
|
||||||
export const routes: RoutesFn = (t) => [
|
export const routes: RoutesFn = (t: TFunction) => [
|
||||||
{
|
{
|
||||||
path: "/:realm/add-realm",
|
path: "/:realm/add-realm",
|
||||||
component: NewRealmForm,
|
component: NewRealmForm,
|
||||||
|
@ -126,7 +126,10 @@ export const routes: RoutesFn = (t) => [
|
||||||
{
|
{
|
||||||
path: "/:realm/groups",
|
path: "/:realm/groups",
|
||||||
component: GroupsSection,
|
component: GroupsSection,
|
||||||
breadcrumb: t("groups"),
|
breadcrumb: null,
|
||||||
|
matchOptions: {
|
||||||
|
exact: false,
|
||||||
|
},
|
||||||
access: "query-groups",
|
access: "query-groups",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue