Adds realm roles section to app and storybook (#79)
* add Realm Roles page * add section for no realm roles * update role-model, fixed UI to match designs * fix paths * add storybook demo and role actions kebab * fix build and clean up * fix formatting * fix lint * fix test and update snapshot * fix storybook demo * update snapshot after rebase * PR feedback from Stan * add back pf addons * Update src/realm-roles/RealmRolesSection.tsx Co-authored-by: Stan Silvert <ssilvert@redhat.com> * fix format * localize NoRealmRoles component * fix formatting * changes to PR suggested by Sarah Co-authored-by: Stan Silvert <ssilvert@redhat.com>
This commit is contained in:
parent
43a4132beb
commit
9fd54eb964
17 changed files with 458 additions and 122 deletions
98
src/App.tsx
98
src/App.tsx
|
@ -29,66 +29,52 @@ export const App = () => {
|
|||
<RealmContextProvider>
|
||||
<Help>
|
||||
<Page header={<Header />} isManagedSidebar sidebar={<PageNav />}>
|
||||
<PageSection variant="light">
|
||||
<Switch>
|
||||
<Route exact path="/add-realm" component={NewRealmForm}></Route>
|
||||
<Switch>
|
||||
<Route exact path="/add-realm" component={NewRealmForm}></Route>
|
||||
|
||||
<Route exact path="/clients" component={ClientsSection}></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/add-client"
|
||||
component={NewClientForm}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/import-client"
|
||||
component={ImportForm}
|
||||
></Route>
|
||||
<Route exact path="/clients" component={ClientsSection}></Route>
|
||||
<Route exact path="/add-client" component={NewClientForm}></Route>
|
||||
<Route exact path="/import-client" component={ImportForm}></Route>
|
||||
|
||||
<Route
|
||||
exact
|
||||
path="/client-scopes"
|
||||
component={ClientScopesSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/realm-roles"
|
||||
component={RealmRolesSection}
|
||||
></Route>
|
||||
<Route exact path="/users" component={UsersSection}></Route>
|
||||
<Route exact path="/groups" component={GroupsSection}></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/sessions"
|
||||
component={SessionsSection}
|
||||
></Route>
|
||||
<Route exact path="/events" component={EventsSection}></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/client-scopes"
|
||||
component={ClientScopesSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/realm-roles"
|
||||
component={RealmRolesSection}
|
||||
></Route>
|
||||
<Route exact path="/users" component={UsersSection}></Route>
|
||||
<Route exact path="/groups" component={GroupsSection}></Route>
|
||||
<Route exact path="/sessions" component={SessionsSection}></Route>
|
||||
<Route exact path="/events" component={EventsSection}></Route>
|
||||
|
||||
<Route
|
||||
exact
|
||||
path="/realm-settings"
|
||||
component={RealmSettingsSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/authentication"
|
||||
component={AuthenticationSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/identity-providers"
|
||||
component={IdentityProvidersSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/user-federation"
|
||||
component={UserFederationSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/realm-settings"
|
||||
component={RealmSettingsSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/authentication"
|
||||
component={AuthenticationSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/identity-providers"
|
||||
component={IdentityProvidersSection}
|
||||
></Route>
|
||||
<Route
|
||||
exact
|
||||
path="/user-federation"
|
||||
component={UserFederationSection}
|
||||
></Route>
|
||||
|
||||
<Route exact path="/" component={ClientsSection} />
|
||||
<Route component={PageNotFoundSection} />
|
||||
</Switch>
|
||||
</PageSection>
|
||||
<Route exact path="/" component={ClientsSection} />
|
||||
<Route component={PageNotFoundSection} />
|
||||
</Switch>
|
||||
</Page>
|
||||
</Help>
|
||||
</RealmContextProvider>
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { PageSection } from "@patternfly/react-core";
|
||||
import React from "react";
|
||||
|
||||
export const ClientScopesSection = () => {
|
||||
return <>The Client Scopes Page</>;
|
||||
return (
|
||||
<>
|
||||
<PageSection variant="light">The Client Scopes Page</PageSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useContext } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "@patternfly/react-core";
|
||||
import { Button, PageSection } from "@patternfly/react-core";
|
||||
|
||||
import { DataLoader } from "../components/data-loader/DataLoader";
|
||||
import { TableToolbar } from "../components/table-toolbar/TableToolbar";
|
||||
|
@ -28,35 +28,40 @@ export const ClientsSection = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<DataLoader loader={loader}>
|
||||
{(clients) => (
|
||||
<TableToolbar
|
||||
count={clients!.length}
|
||||
first={first}
|
||||
max={max}
|
||||
onNextClick={setFirst}
|
||||
onPreviousClick={setFirst}
|
||||
onPerPageSelect={(f, m) => {
|
||||
setFirst(f);
|
||||
setMax(m);
|
||||
}}
|
||||
toolbarItem={
|
||||
<>
|
||||
<Button onClick={() => history.push("/add-client")}>
|
||||
{t("createClient")}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => history.push("/import-client")}
|
||||
variant="link"
|
||||
>
|
||||
{t("importClient")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<ClientList clients={clients} baseUrl={keycloak!.authServerUrl()!} />
|
||||
</TableToolbar>
|
||||
)}
|
||||
</DataLoader>
|
||||
<PageSection variant="light">
|
||||
<DataLoader loader={loader}>
|
||||
{(clients) => (
|
||||
<TableToolbar
|
||||
count={clients!.length}
|
||||
first={first}
|
||||
max={max}
|
||||
onNextClick={setFirst}
|
||||
onPreviousClick={setFirst}
|
||||
onPerPageSelect={(f, m) => {
|
||||
setFirst(f);
|
||||
setMax(m);
|
||||
}}
|
||||
toolbarItem={
|
||||
<>
|
||||
<Button onClick={() => history.push("/add-client")}>
|
||||
{t("createClient")}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => history.push("/import-client")}
|
||||
variant="link"
|
||||
>
|
||||
{t("importClient")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<ClientList
|
||||
clients={clients}
|
||||
baseUrl={keycloak!.authServerUrl()!}
|
||||
/>
|
||||
</TableToolbar>
|
||||
)}
|
||||
</DataLoader>
|
||||
</PageSection>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { PageSection } from "@patternfly/react-core";
|
||||
import React from "react";
|
||||
|
||||
export const EventsSection = () => {
|
||||
return <>The Events Page</>;
|
||||
return (
|
||||
<>
|
||||
<PageSection variant="light">The Events Page</PageSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { Button } from "@patternfly/react-core";
|
||||
import { Button, PageSection } from "@patternfly/react-core";
|
||||
|
||||
import { HttpClientContext } from "../http-service/HttpClientContext";
|
||||
import { GroupsList } from "./GroupsList";
|
||||
|
@ -24,30 +24,32 @@ export const GroupsSection = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<DataLoader loader={loader}>
|
||||
{(groups) => (
|
||||
<TableToolbar
|
||||
count={groups!.length}
|
||||
first={first}
|
||||
max={max}
|
||||
onNextClick={setFirst}
|
||||
onPreviousClick={setFirst}
|
||||
onPerPageSelect={(f, m) => {
|
||||
setFirst(f);
|
||||
setMax(m);
|
||||
}}
|
||||
toolbarItem={
|
||||
<>
|
||||
<Button onClick={() => history.push("/add-group")}>
|
||||
{t("Create group")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<GroupsList list={groups} />
|
||||
</TableToolbar>
|
||||
)}
|
||||
</DataLoader>
|
||||
<PageSection variant="light">
|
||||
<DataLoader loader={loader}>
|
||||
{(groups) => (
|
||||
<TableToolbar
|
||||
count={groups!.length}
|
||||
first={first}
|
||||
max={max}
|
||||
onNextClick={setFirst}
|
||||
onPreviousClick={setFirst}
|
||||
onPerPageSelect={(f, m) => {
|
||||
setFirst(f);
|
||||
setMax(m);
|
||||
}}
|
||||
toolbarItem={
|
||||
<>
|
||||
<Button onClick={() => history.push("/add-group")}>
|
||||
{t("Create group")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<GroupsList list={groups} />
|
||||
</TableToolbar>
|
||||
)}
|
||||
</DataLoader>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,13 +5,14 @@ import { initReactI18next } from "react-i18next";
|
|||
import common from "./common-messages.json";
|
||||
import clients from "./clients/messages.json";
|
||||
import realm from "./realm/messages.json";
|
||||
import roles from "./realm-roles/messages.json";
|
||||
import help from "./help.json";
|
||||
|
||||
const initOptions = {
|
||||
ns: ["common", "help", "clients", "realm"],
|
||||
ns: ["common", "help", "clients", "realm", "roles"],
|
||||
defaultNS: "common",
|
||||
resources: {
|
||||
en: { ...common, ...help, ...clients, ...realm },
|
||||
en: { ...common, ...help, ...clients, ...realm, ...roles },
|
||||
},
|
||||
lng: "en",
|
||||
fallbackLng: "en",
|
||||
|
|
19
src/model/role-model.ts
Normal file
19
src/model/role-model.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Generated using typescript-generator version 2.0.400 on 2020-09-11 12:02:07.
|
||||
|
||||
export interface RoleRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
scopeParamRequired?: boolean;
|
||||
composite?: boolean;
|
||||
composites?: Composites;
|
||||
clientRole?: boolean;
|
||||
containerId?: string;
|
||||
attributes?: { [index: string]: string[] };
|
||||
}
|
||||
|
||||
export interface Composites {
|
||||
realm?: string[];
|
||||
client?: { [index: string]: string[] };
|
||||
application?: { [index: string]: string[] };
|
||||
}
|
35
src/realm-roles/NoRealmRoles.tsx
Normal file
35
src/realm-roles/NoRealmRoles.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
import React from "react";
|
||||
import {
|
||||
Button,
|
||||
PageSection,
|
||||
EmptyState,
|
||||
EmptyStateVariant,
|
||||
EmptyStateIcon,
|
||||
Title,
|
||||
EmptyStateBody,
|
||||
} from "@patternfly/react-core";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import { PlusCircleIcon } from "@patternfly/react-icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export const NoRealmRolesPage = () => {
|
||||
const { t } = useTranslation("realm");
|
||||
const history = useHistory();
|
||||
return (
|
||||
<>
|
||||
<PageSection>
|
||||
<EmptyState variant={EmptyStateVariant.large}>
|
||||
<EmptyStateIcon icon={PlusCircleIcon} />
|
||||
<Title headingLevel="h4" size="lg">
|
||||
{t("noRealmRoles")}
|
||||
</Title>
|
||||
<EmptyStateBody>{t("emptyStateText")}</EmptyStateBody>
|
||||
<Button variant="primary" onClick={() => history.push("/add-role")}>
|
||||
{t("createRealm")}
|
||||
</Button>
|
||||
</EmptyState>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,5 +1,78 @@
|
|||
import React from "react";
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import React, { useState, useContext, useEffect } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
Page,
|
||||
PageSection,
|
||||
PageSectionVariants,
|
||||
Text,
|
||||
TextContent,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { DataLoader } from "../components/data-loader/DataLoader";
|
||||
import { TableToolbar } from "../components/table-toolbar/TableToolbar";
|
||||
import { HttpClientContext } from "../http-service/HttpClientContext";
|
||||
import { RoleRepresentation } from "../model/role-model";
|
||||
import { RolesList } from "./RoleList";
|
||||
import { RealmContext } from "../components/realm-context/RealmContext";
|
||||
|
||||
export const RealmRolesSection = () => {
|
||||
return <>The Realm Roles Page</>;
|
||||
const { t } = useTranslation("roles");
|
||||
const history = useHistory();
|
||||
const [max, setMax] = useState(10);
|
||||
const [, setRoles] = useState([] as RoleRepresentation[]);
|
||||
const [first, setFirst] = useState(0);
|
||||
const httpClient = useContext(HttpClientContext)!;
|
||||
const { realm } = useContext(RealmContext);
|
||||
|
||||
const loader = async () => {
|
||||
return await httpClient
|
||||
.doGet(`/admin/realms/${realm}/roles`)
|
||||
.then((r) => r.data as RoleRepresentation[]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loader().then((result) => setRoles(result || []));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DataLoader loader={loader}>
|
||||
{(roles) => (
|
||||
<>
|
||||
<PageSection variant="light">
|
||||
<TextContent>
|
||||
<Text component="h1">Realm roles</Text>
|
||||
<Text component="p">{t("roleExplain")}</Text>
|
||||
</TextContent>
|
||||
</PageSection>
|
||||
<Divider component="li" key={1} />
|
||||
<PageSection padding={{ default: "noPadding" }}>
|
||||
<TableToolbar
|
||||
count={roles!.length}
|
||||
first={first}
|
||||
max={max}
|
||||
onNextClick={setFirst}
|
||||
onPreviousClick={setFirst}
|
||||
onPerPageSelect={(f, m) => {
|
||||
setFirst(f);
|
||||
setMax(m);
|
||||
}}
|
||||
toolbarItem={
|
||||
<>
|
||||
<Button onClick={() => history.push("/add-role")}>
|
||||
{t("createRole")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<RolesList roles={roles} />
|
||||
</TableToolbar>
|
||||
</PageSection>
|
||||
</>
|
||||
)}
|
||||
</DataLoader>
|
||||
);
|
||||
};
|
||||
|
|
79
src/realm-roles/RoleList.tsx
Normal file
79
src/realm-roles/RoleList.tsx
Normal file
|
@ -0,0 +1,79 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableHeader,
|
||||
TableVariant,
|
||||
IFormatter,
|
||||
IFormatterValueType,
|
||||
} from "@patternfly/react-table";
|
||||
|
||||
import { ExternalLink } from "../components/external-link/ExternalLink";
|
||||
import { RoleRepresentation } from "../model/role-model";
|
||||
|
||||
type RolesListProps = {
|
||||
roles?: RoleRepresentation[];
|
||||
};
|
||||
|
||||
const columns: (keyof RoleRepresentation)[] = [
|
||||
"name",
|
||||
"composite",
|
||||
"description",
|
||||
];
|
||||
|
||||
export const RolesList = ({ roles }: RolesListProps) => {
|
||||
const { t } = useTranslation("roles");
|
||||
|
||||
const emptyFormatter = (): IFormatter => (data?: IFormatterValueType) => {
|
||||
return data ? data : "—";
|
||||
};
|
||||
|
||||
const externalLink = (): IFormatter => (data?: IFormatterValueType) => {
|
||||
return (data ? (
|
||||
<ExternalLink href={data.toString()} />
|
||||
) : undefined) as object;
|
||||
};
|
||||
|
||||
const boolFormatter = (): IFormatter => (data?: IFormatterValueType) => {
|
||||
const boolVal = data?.toString();
|
||||
|
||||
return (boolVal
|
||||
? boolVal.charAt(0).toUpperCase() + boolVal.slice(1)
|
||||
: undefined) as string;
|
||||
};
|
||||
|
||||
const data = roles!.map((c) => {
|
||||
return { cells: columns.map((col) => c[col]) };
|
||||
});
|
||||
return (
|
||||
<Table
|
||||
variant={TableVariant.compact}
|
||||
cells={[
|
||||
{
|
||||
title: t("roleName"),
|
||||
cellFormatters: [externalLink(), emptyFormatter()],
|
||||
},
|
||||
{
|
||||
title: t("composite"),
|
||||
cellFormatters: [boolFormatter(), emptyFormatter()],
|
||||
},
|
||||
{ title: t("description"), cellFormatters: [emptyFormatter()] },
|
||||
]}
|
||||
rows={data}
|
||||
actions={[
|
||||
{
|
||||
title: t("common:Export"),
|
||||
},
|
||||
{
|
||||
title: t("common:Delete"),
|
||||
},
|
||||
]}
|
||||
aria-label="Roles list"
|
||||
>
|
||||
<TableHeader />
|
||||
<TableBody />
|
||||
</Table>
|
||||
);
|
||||
};
|
77
src/realm-roles/__tests__/mock-roles.json
Normal file
77
src/realm-roles/__tests__/mock-roles.json
Normal file
|
@ -0,0 +1,77 @@
|
|||
[
|
||||
{
|
||||
"name":"Admin",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Author",
|
||||
"composite":false,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Billing",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit"
|
||||
},
|
||||
{
|
||||
"name":"Contributor",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit, consecte"
|
||||
},
|
||||
{
|
||||
"name":"Editor",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Engineer",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Member",
|
||||
"composite":false,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Moderator",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Owner",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Reader",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
{
|
||||
"name":"Subscriber",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit "
|
||||
},
|
||||
{
|
||||
"name":"Teenager",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet, consecte occaecat"
|
||||
},
|
||||
{
|
||||
"name":"User",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet, consecte"
|
||||
},
|
||||
{
|
||||
"name":"Writer",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor"
|
||||
},
|
||||
{
|
||||
"name":"Zara",
|
||||
"composite":true,
|
||||
"description": "Lorem ipsum dolor sit amet"
|
||||
}
|
||||
]
|
22
src/realm-roles/messages.json
Normal file
22
src/realm-roles/messages.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"roles": {
|
||||
"createRole": "Create role",
|
||||
"importRole": "Import role",
|
||||
"roleID": "Role ID",
|
||||
"type": "Type",
|
||||
"homeURL": "Home URL",
|
||||
"roleExplain": "Realm-level roles are a global namespace to define your roles.",
|
||||
"roleName": "Role name",
|
||||
"composite": "Composite",
|
||||
"description": "Description",
|
||||
"roleList": "Role list",
|
||||
"generalSettings": "General Settings",
|
||||
"capabilityConfig": "Capability config",
|
||||
"roleImportError": "Could not import role",
|
||||
"roleImportSuccess": "Role imported succeful",
|
||||
"roleDeletedSucess": "The role has been deleted",
|
||||
"roleDeleteError": "Could not delete role:",
|
||||
"roleAuthentication": "Role authentication"
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@
|
|||
"uploadFile":"Upload JSON file",
|
||||
"realmName":"Realm name",
|
||||
"enabled":"Enabled",
|
||||
"create":"Create"
|
||||
"create":"Create",
|
||||
"createRealm": "Create realm",
|
||||
"noRealmRoles": "No realm roles",
|
||||
"emptyStateText": "There aren't any realm roles in this realm. Create a realm role to get started."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
import { PageSection } from "@patternfly/react-core";
|
||||
import React from "react";
|
||||
|
||||
export const SessionsSection = () => {
|
||||
return <>The Sessions Page</>;
|
||||
return (
|
||||
<>
|
||||
<>
|
||||
<PageSection variant="light">The Sessions Page</PageSection>
|
||||
</>
|
||||
;
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Page } from "@patternfly/react-core";
|
|||
import { NewRealmForm } from "../realm/add/NewRealmForm";
|
||||
|
||||
export default {
|
||||
title: "New reaml form",
|
||||
title: "New realm form",
|
||||
component: NewRealmForm,
|
||||
} as Meta;
|
||||
|
||||
|
|
11
src/stories/RealmRoles.stories.tsx
Normal file
11
src/stories/RealmRoles.stories.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React from "react";
|
||||
import { Meta } from "@storybook/react";
|
||||
import { RolesList } from "../realm-roles/RoleList";
|
||||
import rolesMock from "../realm-roles/__tests__/mock-roles.json";
|
||||
|
||||
export default {
|
||||
title: "Roles List",
|
||||
component: RolesList,
|
||||
} as Meta;
|
||||
|
||||
export const RolesListExample = () => <RolesList roles={rolesMock} />;
|
|
@ -1,5 +1,10 @@
|
|||
import { PageSection } from "@patternfly/react-core";
|
||||
import React from "react";
|
||||
|
||||
export const UsersSection = () => {
|
||||
return <>The Users Page</>;
|
||||
return (
|
||||
<>
|
||||
<PageSection variant="light">The Users Page</PageSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue