updated the realm selector (#90)
* updated the realm selector with: 1. realm context that works on other requests 2. added search bar when realm list > 5 realms * fixed merge
This commit is contained in:
parent
79c8942eeb
commit
b87bd2ca76
13 changed files with 639 additions and 169 deletions
111
src/App.tsx
111
src/App.tsx
|
@ -21,62 +21,77 @@ import { IdentityProvidersSection } from "./identity-providers/IdentityProviders
|
|||
import { UserFederationSection } from "./user-federation/UserFederationSection";
|
||||
|
||||
import { PageNotFoundSection } from "./PageNotFoundSection";
|
||||
import { RealmContextProvider } from "./components/realm-context/RealmContext";
|
||||
|
||||
export const App = () => {
|
||||
return (
|
||||
<Router>
|
||||
<Help>
|
||||
<Page header={<Header />} isManagedSidebar sidebar={<PageNav />}>
|
||||
<PageSection variant="light">
|
||||
<Switch>
|
||||
<Route exact path="/add-realm" component={NewRealmForm}></Route>
|
||||
<RealmContextProvider>
|
||||
<Help>
|
||||
<Page header={<Header />} isManagedSidebar sidebar={<PageNav />}>
|
||||
<PageSection variant="light">
|
||||
<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>
|
||||
</Page>
|
||||
</Help>
|
||||
<Route exact path="/" component={ClientsSection} />
|
||||
<Route component={PageNotFoundSection} />
|
||||
</Switch>
|
||||
</PageSection>
|
||||
</Page>
|
||||
</Help>
|
||||
</RealmContextProvider>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -54,36 +54,36 @@ export const PageNav: React.FunctionComponent = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<PageSidebar
|
||||
nav={
|
||||
<Nav onSelect={onSelect}>
|
||||
<NavList>
|
||||
<NavItem className="keycloak__page_nav__nav_item__realm-selector">
|
||||
<DataLoader loader={realmLoader}>
|
||||
{(realmList) => (
|
||||
<RealmSelector realm="Master" realmList={realmList || []} />
|
||||
)}
|
||||
</DataLoader>
|
||||
</NavItem>
|
||||
</NavList>
|
||||
<NavGroup title="Manage">
|
||||
{makeNavItem("Clients", "clients")}
|
||||
{makeNavItem("Client Scopes", "client-scopes")}
|
||||
{makeNavItem("Realm Roles", "realm-roles")}
|
||||
{makeNavItem("Users", "users")}
|
||||
{makeNavItem("Groups", "groups")}
|
||||
{makeNavItem("Sessions", "sessions")}
|
||||
{makeNavItem("Events", "events")}
|
||||
</NavGroup>
|
||||
<DataLoader loader={realmLoader}>
|
||||
{(realmList) => (
|
||||
<PageSidebar
|
||||
nav={
|
||||
<Nav onSelect={onSelect}>
|
||||
<NavList>
|
||||
<NavItem className="keycloak__page_nav__nav_item__realm-selector">
|
||||
<RealmSelector realmList={realmList || []} />
|
||||
</NavItem>
|
||||
</NavList>
|
||||
<NavGroup title="Manage">
|
||||
{makeNavItem("Clients", "clients")}
|
||||
{makeNavItem("Client Scopes", "client-scopes")}
|
||||
{makeNavItem("Realm Roles", "realm-roles")}
|
||||
{makeNavItem("Users", "users")}
|
||||
{makeNavItem("Groups", "groups")}
|
||||
{makeNavItem("Sessions", "sessions")}
|
||||
{makeNavItem("Events", "events")}
|
||||
</NavGroup>
|
||||
|
||||
<NavGroup title="Configure">
|
||||
{makeNavItem("Realm settings", "realm-settings")}
|
||||
{makeNavItem("Authentication", "authentication")}
|
||||
{makeNavItem("Identity providers", "identity-providers")}
|
||||
{makeNavItem("User federation", "user-federation")}
|
||||
</NavGroup>
|
||||
</Nav>
|
||||
}
|
||||
/>
|
||||
<NavGroup title="Configure">
|
||||
{makeNavItem("Realm settings", "realm-settings")}
|
||||
{makeNavItem("Authentication", "authentication")}
|
||||
{makeNavItem("Identity providers", "identity-providers")}
|
||||
{makeNavItem("User federation", "user-federation")}
|
||||
</NavGroup>
|
||||
</Nav>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</DataLoader>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ import { ExternalLink } from "../components/external-link/ExternalLink";
|
|||
import { HttpClientContext } from "../http-service/HttpClientContext";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { ClientRepresentation } from "./models/client-model";
|
||||
import { RealmContext } from "../components/realm-context/RealmContext";
|
||||
|
||||
type ClientListProps = {
|
||||
clients?: ClientRepresentation[];
|
||||
|
@ -31,6 +32,7 @@ const columns: (keyof ClientRepresentation)[] = [
|
|||
export const ClientList = ({ baseUrl, clients }: ClientListProps) => {
|
||||
const { t } = useTranslation("clients");
|
||||
const httpClient = useContext(HttpClientContext)!;
|
||||
const { realm } = useContext(RealmContext);
|
||||
const [add, Alerts] = useAlerts();
|
||||
|
||||
const convertClientId = (clientId: string) =>
|
||||
|
@ -116,7 +118,7 @@ export const ClientList = ({ baseUrl, clients }: ClientListProps) => {
|
|||
onClick: (_, rowId) => {
|
||||
try {
|
||||
httpClient.doDelete(
|
||||
`/admin/realms/master/clients/${data[rowId].client.id}`
|
||||
`/admin/realms/${realm}/clients/${data[rowId].client.id}`
|
||||
);
|
||||
add(t("clientDeletedSucess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
|
|
|
@ -9,18 +9,21 @@ import { ClientList } from "./ClientList";
|
|||
import { HttpClientContext } from "../http-service/HttpClientContext";
|
||||
import { KeycloakContext } from "../auth/KeycloakContext";
|
||||
import { ClientRepresentation } from "./models/client-model";
|
||||
import { RealmContext } from "../components/realm-context/RealmContext";
|
||||
|
||||
export const ClientsSection = () => {
|
||||
const { t } = useTranslation("clients");
|
||||
const history = useHistory();
|
||||
|
||||
const [max, setMax] = useState(10);
|
||||
const [first, setFirst] = useState(0);
|
||||
const httpClient = useContext(HttpClientContext)!;
|
||||
const keycloak = useContext(KeycloakContext);
|
||||
const { realm } = useContext(RealmContext);
|
||||
|
||||
const loader = async () => {
|
||||
return await httpClient
|
||||
.doGet("/admin/realms/master/clients", { params: { first, max } })
|
||||
.doGet(`/admin/realms/${realm}/clients`, { params: { first, max } })
|
||||
.then((r) => r.data as ClientRepresentation[]);
|
||||
};
|
||||
|
||||
|
|
|
@ -13,10 +13,13 @@ import { Step2 } from "./Step2";
|
|||
import { ClientRepresentation } from "../models/client-model";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RealmContext } from "../../components/realm-context/RealmContext";
|
||||
|
||||
export const NewClientForm = () => {
|
||||
const { t } = useTranslation("clients");
|
||||
const httpClient = useContext(HttpClientContext)!;
|
||||
const { realm } = useContext(RealmContext);
|
||||
|
||||
const [client, setClient] = useState<ClientRepresentation>({
|
||||
protocol: "",
|
||||
clientId: "",
|
||||
|
@ -29,7 +32,7 @@ export const NewClientForm = () => {
|
|||
|
||||
const save = async () => {
|
||||
try {
|
||||
await httpClient.doPost("/admin/realms/master/clients", client);
|
||||
await httpClient.doPost(`/admin/realms/${realm}/clients`, client);
|
||||
add("Client created", AlertVariant.success);
|
||||
} catch (error) {
|
||||
add(`Could not create client: '${error}'`, AlertVariant.danger);
|
||||
|
|
|
@ -18,10 +18,13 @@ import { ClientDescription } from "../ClientDescription";
|
|||
import { HttpClientContext } from "../../http-service/HttpClientContext";
|
||||
import { JsonFileUpload } from "../../components/json-file-upload/JsonFileUpload";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { AlertPanel } from "../../components/alert/AlertPanel";
|
||||
import { RealmContext } from "../../components/realm-context/RealmContext";
|
||||
|
||||
export const ImportForm = () => {
|
||||
const { t } = useTranslation("clients");
|
||||
const httpClient = useContext(HttpClientContext)!;
|
||||
const { realm } = useContext(RealmContext);
|
||||
|
||||
const [add, Alerts] = useAlerts();
|
||||
const defaultClient = {
|
||||
|
@ -48,7 +51,7 @@ export const ImportForm = () => {
|
|||
|
||||
const save = async () => {
|
||||
try {
|
||||
await httpClient.doPost("/admin/realms/master/clients", client);
|
||||
await httpClient.doPost(`/admin/realms/${realm}/clients`, client);
|
||||
add(t("clientImportSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
add(`${t("clientImportError")} '${error}'`, AlertVariant.danger);
|
||||
|
|
20
src/components/realm-context/RealmContext.tsx
Normal file
20
src/components/realm-context/RealmContext.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
export const RealmContext = React.createContext({
|
||||
realm: "master",
|
||||
setRealm: (realm: string) => {},
|
||||
});
|
||||
|
||||
type RealmContextProviderProps = { children: React.ReactNode };
|
||||
|
||||
export const RealmContextProvider = ({
|
||||
children,
|
||||
}: RealmContextProviderProps) => {
|
||||
const [realm, setRealm] = useState("master");
|
||||
|
||||
return (
|
||||
<RealmContext.Provider value={{ realm, setRealm }}>
|
||||
{children}
|
||||
</RealmContext.Provider>
|
||||
);
|
||||
};
|
|
@ -1,6 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useState, useContext } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { RealmRepresentation } from "../../realm/models/Realm";
|
||||
|
||||
import {
|
||||
Dropdown,
|
||||
|
@ -8,55 +7,118 @@ import {
|
|||
DropdownItem,
|
||||
Button,
|
||||
Divider,
|
||||
SplitItem,
|
||||
Split,
|
||||
ContextSelector,
|
||||
ContextSelectorItem,
|
||||
} from "@patternfly/react-core";
|
||||
import { CheckIcon } from "@patternfly/react-icons";
|
||||
|
||||
import { RealmRepresentation } from "../../realm/models/Realm";
|
||||
import { RealmContext } from "../realm-context/RealmContext";
|
||||
|
||||
import "./realm-selector.css";
|
||||
|
||||
type RealmSelectorProps = {
|
||||
realm: string;
|
||||
realmList: RealmRepresentation[];
|
||||
};
|
||||
|
||||
export const RealmSelector = ({ realm, realmList }: RealmSelectorProps) => {
|
||||
export const RealmSelector = ({ realmList }: RealmSelectorProps) => {
|
||||
const { realm, setRealm } = useContext(RealmContext);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [search, setSearch] = useState("");
|
||||
const [filteredItems, setFilteredItems] = useState(realmList);
|
||||
const history = useHistory();
|
||||
const [currentRealm, setCurrentRealm] = useState(realm);
|
||||
|
||||
const toUpperCase = (realmName: string) =>
|
||||
realmName.charAt(0).toUpperCase() + realmName.slice(1);
|
||||
|
||||
const RealmText = ({ value }: { value: string }) => (
|
||||
<Split>
|
||||
<SplitItem isFilled>{toUpperCase(value)}</SplitItem>
|
||||
<SplitItem>{value === realm && <CheckIcon />}</SplitItem>
|
||||
</Split>
|
||||
);
|
||||
|
||||
const AddRealm = () => (
|
||||
<Button component="div" isBlock onClick={() => history.push("/add-realm")}>
|
||||
Create Realm
|
||||
</Button>
|
||||
);
|
||||
|
||||
const onFilter = () => {
|
||||
const filtered =
|
||||
search === ""
|
||||
? realmList
|
||||
: realmList.filter(
|
||||
(r) => r.realm.toLowerCase().indexOf(search.toLowerCase()) !== -1
|
||||
);
|
||||
setFilteredItems(filtered || []);
|
||||
};
|
||||
|
||||
const dropdownItems = realmList.map((r) => (
|
||||
<DropdownItem
|
||||
key={r.id}
|
||||
onClick={() => {
|
||||
setCurrentRealm(r.realm);
|
||||
setRealm(r.realm);
|
||||
setOpen(!open);
|
||||
}}
|
||||
>
|
||||
{r.realm.charAt(0).toUpperCase() + r.realm.slice(1)}
|
||||
<RealmText value={r.realm} />
|
||||
</DropdownItem>
|
||||
));
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
id="realm-select"
|
||||
className="keycloak__realm_selector__dropdown"
|
||||
isOpen={open}
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
id="realm-select-toggle"
|
||||
<>
|
||||
{realmList.length > 5 && (
|
||||
<ContextSelector
|
||||
toggleText={toUpperCase(realm)}
|
||||
isOpen={open}
|
||||
screenReaderLabel={toUpperCase(realm)}
|
||||
onToggle={() => setOpen(!open)}
|
||||
className="keycloak__realm_selector_dropdown__toggle"
|
||||
onSelect={(_, r) => {
|
||||
const value = ((r as unknown) as any).props.value;
|
||||
setRealm(value || "master");
|
||||
setOpen(!open);
|
||||
}}
|
||||
searchInputValue={search}
|
||||
onSearchInputChange={(value) => setSearch(value)}
|
||||
onSearchButtonClick={() => onFilter()}
|
||||
className="keycloak__realm_selector__context_selector"
|
||||
>
|
||||
{currentRealm}
|
||||
</DropdownToggle>
|
||||
}
|
||||
dropdownItems={[
|
||||
...dropdownItems,
|
||||
<Divider key={1} />,
|
||||
<DropdownItem component="div" key="add">
|
||||
<Button isBlock onClick={() => history.push("/add-realm")}>
|
||||
Create Realm
|
||||
</Button>
|
||||
</DropdownItem>,
|
||||
]}
|
||||
/>
|
||||
{filteredItems.map((item) => (
|
||||
<ContextSelectorItem key={item.id}>
|
||||
<RealmText value={item.realm} />
|
||||
</ContextSelectorItem>
|
||||
))}
|
||||
<ContextSelectorItem key="add">
|
||||
<AddRealm />
|
||||
</ContextSelectorItem>
|
||||
</ContextSelector>
|
||||
)}
|
||||
{realmList.length <= 5 && (
|
||||
<Dropdown
|
||||
id="realm-select"
|
||||
className="keycloak__realm_selector__dropdown"
|
||||
isOpen={open}
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
id="realm-select-toggle"
|
||||
onToggle={() => setOpen(!open)}
|
||||
className="keycloak__realm_selector_dropdown__toggle"
|
||||
>
|
||||
{toUpperCase(realm)}
|
||||
</DropdownToggle>
|
||||
}
|
||||
dropdownItems={[
|
||||
...dropdownItems,
|
||||
<Divider key="divider" />,
|
||||
<DropdownItem key="add">
|
||||
<AddRealm />
|
||||
</DropdownItem>,
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -3,18 +3,21 @@ import { mount } from "enzyme";
|
|||
import { act } from "@testing-library/react";
|
||||
|
||||
import { RealmSelector } from "../RealmSelector";
|
||||
import { RealmContextProvider } from "../../realm-context/RealmContext";
|
||||
|
||||
it("renders realm selector", async () => {
|
||||
const wrapper = mount(
|
||||
<RealmSelector realm="test" realmList={[{ id: "321", realm: "another" }]} />
|
||||
<RealmContextProvider>
|
||||
<RealmSelector realmList={[{ id: "321", realm: "another" }]} />
|
||||
</RealmContextProvider>
|
||||
);
|
||||
|
||||
expect(wrapper.text()).toBe("test");
|
||||
expect(wrapper.text()).toBe("Master");
|
||||
|
||||
const expandButton = wrapper.find("button");
|
||||
act(() => {
|
||||
expandButton!.simulate("click");
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -1,3 +1,353 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders realm selector 1`] = `"<div id=\\"realm-select\\" class=\\"pf-c-dropdown pf-m-expanded keycloak__realm_selector__dropdown\\" data-ouia-component-type=\\"PF4/Dropdown\\" data-ouia-safe=\\"true\\" data-ouia-component-id=\\"1\\"><button id=\\"realm-select-toggle\\" class=\\"pf-c-dropdown__toggle keycloak__realm_selector_dropdown__toggle\\" type=\\"button\\" aria-expanded=\\"true\\" aria-haspopup=\\"true\\"><span class=\\"pf-c-dropdown__toggle-text\\">test</span><span class=\\"pf-c-dropdown__toggle-icon\\"><svg style=\\"vertical-align: -0.125em;\\" fill=\\"currentColor\\" height=\\"1em\\" width=\\"1em\\" viewBox=\\"0 0 320 512\\" aria-hidden=\\"true\\" role=\\"img\\"><path d=\\"M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z\\" transform=\\"\\"></path></svg></span></button><ul aria-labelledby=\\"realm-select-toggle\\" class=\\"pf-c-dropdown__menu\\" role=\\"menu\\"><li role=\\"menuitem\\"><a tabindex=\\"-1\\" aria-disabled=\\"false\\" class=\\"pf-c-dropdown__menu-item\\">Another</a></li><hr class=\\"pf-c-divider\\" index=\\"1\\"><li role=\\"menuitem\\"><div tabindex=\\"-1\\" class=\\"pf-c-dropdown__menu-item\\"><button aria-disabled=\\"false\\" class=\\"pf-c-button pf-m-primary pf-m-block\\" type=\\"button\\" data-ouia-component-type=\\"PF4/Button\\" data-ouia-safe=\\"true\\" data-ouia-component-id=\\"2\\">Create Realm</button></div></li></ul></div>"`;
|
||||
exports[`renders realm selector 1`] = `
|
||||
<RealmContextProvider>
|
||||
<RealmSelector
|
||||
realmList={
|
||||
Array [
|
||||
Object {
|
||||
"id": "321",
|
||||
"realm": "another",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
<Dropdown
|
||||
className="keycloak__realm_selector__dropdown"
|
||||
dropdownItems={
|
||||
Array [
|
||||
<DropdownItem
|
||||
onClick={[Function]}
|
||||
>
|
||||
<RealmText
|
||||
value="another"
|
||||
/>
|
||||
</DropdownItem>,
|
||||
<Divider />,
|
||||
<DropdownItem>
|
||||
<AddRealm />
|
||||
</DropdownItem>,
|
||||
]
|
||||
}
|
||||
id="realm-select"
|
||||
isOpen={false}
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
className="keycloak__realm_selector_dropdown__toggle"
|
||||
id="realm-select-toggle"
|
||||
onToggle={[Function]}
|
||||
>
|
||||
Master
|
||||
</DropdownToggle>
|
||||
}
|
||||
>
|
||||
<DropdownWithContext
|
||||
autoFocus={true}
|
||||
className="keycloak__realm_selector__dropdown"
|
||||
direction="down"
|
||||
dropdownItems={
|
||||
Array [
|
||||
<DropdownItem
|
||||
onClick={[Function]}
|
||||
>
|
||||
<RealmText
|
||||
value="another"
|
||||
/>
|
||||
</DropdownItem>,
|
||||
<Divider />,
|
||||
<DropdownItem>
|
||||
<AddRealm />
|
||||
</DropdownItem>,
|
||||
]
|
||||
}
|
||||
id="realm-select"
|
||||
isGrouped={false}
|
||||
isOpen={false}
|
||||
isPlain={false}
|
||||
menuAppendTo="inline"
|
||||
onSelect={[Function]}
|
||||
position="left"
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
className="keycloak__realm_selector_dropdown__toggle"
|
||||
id="realm-select-toggle"
|
||||
onToggle={[Function]}
|
||||
>
|
||||
Master
|
||||
</DropdownToggle>
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="pf-c-dropdown keycloak__realm_selector__dropdown"
|
||||
data-ouia-component-id={0}
|
||||
data-ouia-component-type="PF4/Dropdown"
|
||||
data-ouia-safe={true}
|
||||
id="realm-select"
|
||||
>
|
||||
<DropdownToggle
|
||||
aria-haspopup={true}
|
||||
className="keycloak__realm_selector_dropdown__toggle"
|
||||
getMenuRef={[Function]}
|
||||
id="realm-select-toggle"
|
||||
isOpen={false}
|
||||
isPlain={false}
|
||||
key=".0"
|
||||
onEnter={[Function]}
|
||||
onToggle={[Function]}
|
||||
parentRef={
|
||||
Object {
|
||||
"current": <div
|
||||
class="pf-c-dropdown pf-m-expanded keycloak__realm_selector__dropdown"
|
||||
data-ouia-component-id="1"
|
||||
data-ouia-component-type="PF4/Dropdown"
|
||||
data-ouia-safe="true"
|
||||
id="realm-select"
|
||||
>
|
||||
<button
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
class="pf-c-dropdown__toggle keycloak__realm_selector_dropdown__toggle"
|
||||
id="realm-select-toggle"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="pf-c-dropdown__toggle-text"
|
||||
>
|
||||
Master
|
||||
</span>
|
||||
<span
|
||||
class="pf-c-dropdown__toggle-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
style="vertical-align: -0.125em;"
|
||||
viewBox="0 0 320 512"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
|
||||
transform=""
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<ul
|
||||
aria-labelledby="realm-select-toggle"
|
||||
class="pf-c-dropdown__menu"
|
||||
role="menu"
|
||||
>
|
||||
<li
|
||||
role="menuitem"
|
||||
>
|
||||
<a
|
||||
aria-disabled="false"
|
||||
class="pf-c-dropdown__menu-item"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="pf-l-split"
|
||||
>
|
||||
<div
|
||||
class="pf-l-split__item pf-m-fill"
|
||||
>
|
||||
Another
|
||||
</div>
|
||||
<div
|
||||
class="pf-l-split__item"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<hr
|
||||
class="pf-c-divider"
|
||||
index="1"
|
||||
/>
|
||||
<li
|
||||
role="menuitem"
|
||||
>
|
||||
<a
|
||||
aria-disabled="false"
|
||||
class="pf-c-dropdown__menu-item"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
aria-disabled="false"
|
||||
class="pf-c-button pf-m-primary pf-m-block"
|
||||
data-ouia-component-id="2"
|
||||
data-ouia-component-type="PF4/Button"
|
||||
data-ouia-safe="true"
|
||||
>
|
||||
Create Realm
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Toggle
|
||||
aria-haspopup={true}
|
||||
bubbleEvent={false}
|
||||
className="keycloak__realm_selector_dropdown__toggle"
|
||||
getMenuRef={[Function]}
|
||||
id="realm-select-toggle"
|
||||
isActive={false}
|
||||
isDisabled={false}
|
||||
isOpen={false}
|
||||
isPlain={false}
|
||||
isPrimary={false}
|
||||
isSplitButton={false}
|
||||
onEnter={[Function]}
|
||||
onToggle={[Function]}
|
||||
parentRef={
|
||||
Object {
|
||||
"current": <div
|
||||
class="pf-c-dropdown pf-m-expanded keycloak__realm_selector__dropdown"
|
||||
data-ouia-component-id="1"
|
||||
data-ouia-component-type="PF4/Dropdown"
|
||||
data-ouia-safe="true"
|
||||
id="realm-select"
|
||||
>
|
||||
<button
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
class="pf-c-dropdown__toggle keycloak__realm_selector_dropdown__toggle"
|
||||
id="realm-select-toggle"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="pf-c-dropdown__toggle-text"
|
||||
>
|
||||
Master
|
||||
</span>
|
||||
<span
|
||||
class="pf-c-dropdown__toggle-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
style="vertical-align: -0.125em;"
|
||||
viewBox="0 0 320 512"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
|
||||
transform=""
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<ul
|
||||
aria-labelledby="realm-select-toggle"
|
||||
class="pf-c-dropdown__menu"
|
||||
role="menu"
|
||||
>
|
||||
<li
|
||||
role="menuitem"
|
||||
>
|
||||
<a
|
||||
aria-disabled="false"
|
||||
class="pf-c-dropdown__menu-item"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="pf-l-split"
|
||||
>
|
||||
<div
|
||||
class="pf-l-split__item pf-m-fill"
|
||||
>
|
||||
Another
|
||||
</div>
|
||||
<div
|
||||
class="pf-l-split__item"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<hr
|
||||
class="pf-c-divider"
|
||||
index="1"
|
||||
/>
|
||||
<li
|
||||
role="menuitem"
|
||||
>
|
||||
<a
|
||||
aria-disabled="false"
|
||||
class="pf-c-dropdown__menu-item"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
aria-disabled="false"
|
||||
class="pf-c-button pf-m-primary pf-m-block"
|
||||
data-ouia-component-id="2"
|
||||
data-ouia-component-type="PF4/Button"
|
||||
data-ouia-safe="true"
|
||||
>
|
||||
Create Realm
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>,
|
||||
}
|
||||
}
|
||||
>
|
||||
<button
|
||||
aria-expanded={false}
|
||||
aria-haspopup={true}
|
||||
className="pf-c-dropdown__toggle keycloak__realm_selector_dropdown__toggle"
|
||||
disabled={false}
|
||||
id="realm-select-toggle"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
className="pf-c-dropdown__toggle-text"
|
||||
>
|
||||
Master
|
||||
</span>
|
||||
<span
|
||||
className="pf-c-dropdown__toggle-icon"
|
||||
>
|
||||
<CaretDownIcon
|
||||
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 320 512"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
|
||||
transform=""
|
||||
/>
|
||||
</svg>
|
||||
</CaretDownIcon>
|
||||
</span>
|
||||
</button>
|
||||
</Toggle>
|
||||
</DropdownToggle>
|
||||
</div>
|
||||
</DropdownWithContext>
|
||||
</Dropdown>
|
||||
</RealmSelector>
|
||||
</RealmContextProvider>
|
||||
`;
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.keycloak__realm_selector__context_selector {
|
||||
--pf-c-context-selector__toggle--Color: var(--pf-c-nav__link--m-current--Color);
|
||||
}
|
||||
|
||||
.keycloak__realm_selector__dropdown {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
60
src/stories/Toobar.stories.tsx
Normal file
60
src/stories/Toobar.stories.tsx
Normal file
|
@ -0,0 +1,60 @@
|
|||
import React from "react";
|
||||
import {
|
||||
Nav,
|
||||
NavItem,
|
||||
NavList,
|
||||
PageSidebar,
|
||||
Page,
|
||||
} from "@patternfly/react-core";
|
||||
import { Meta } from "@storybook/react";
|
||||
|
||||
import { RealmSelector } from "../components/realm-selector/RealmSelector";
|
||||
import { RealmContextProvider } from "../components/realm-context/RealmContext";
|
||||
|
||||
export default {
|
||||
title: "Header",
|
||||
component: RealmSelector,
|
||||
} as Meta;
|
||||
|
||||
export const Header = () => {
|
||||
return (
|
||||
<RealmContextProvider>
|
||||
<Page
|
||||
sidebar={
|
||||
<PageSidebar
|
||||
nav={
|
||||
<Nav>
|
||||
<NavList>
|
||||
<RealmSelector
|
||||
realmList={[
|
||||
{ id: "master", realm: "Master" },
|
||||
{ id: "photoz", realm: "Photoz" },
|
||||
]}
|
||||
/>
|
||||
|
||||
<NavItem id="default-link1" to="#default-link1" itemId={0}>
|
||||
Link 1
|
||||
</NavItem>
|
||||
<NavItem
|
||||
id="default-link2"
|
||||
to="#default-link2"
|
||||
itemId={1}
|
||||
isActive
|
||||
>
|
||||
Current link
|
||||
</NavItem>
|
||||
<NavItem id="default-link3" to="#default-link3" itemId={2}>
|
||||
Link 3
|
||||
</NavItem>
|
||||
<NavItem id="default-link4" to="#default-link4" itemId={3}>
|
||||
Link 4
|
||||
</NavItem>
|
||||
</NavList>
|
||||
</Nav>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</RealmContextProvider>
|
||||
);
|
||||
};
|
|
@ -1,55 +0,0 @@
|
|||
import React from "react";
|
||||
import {
|
||||
Nav,
|
||||
NavItem,
|
||||
NavList,
|
||||
PageSidebar,
|
||||
Page,
|
||||
} from "@patternfly/react-core";
|
||||
import { Meta } from "@storybook/react";
|
||||
|
||||
import { RealmSelector } from "../components/realm-selector/RealmSelector";
|
||||
|
||||
export default {
|
||||
title: "Header",
|
||||
component: RealmSelector,
|
||||
} as Meta;
|
||||
|
||||
export const Header = () => {
|
||||
return (
|
||||
<Page
|
||||
sidebar={
|
||||
<PageSidebar
|
||||
nav={
|
||||
<Nav>
|
||||
<NavList>
|
||||
<RealmSelector
|
||||
realm="Master"
|
||||
realmList={["Master", "Photoz"]}
|
||||
/>
|
||||
|
||||
<NavItem id="default-link1" to="#default-link1" itemId={0}>
|
||||
Link 1
|
||||
</NavItem>
|
||||
<NavItem
|
||||
id="default-link2"
|
||||
to="#default-link2"
|
||||
itemId={1}
|
||||
isActive
|
||||
>
|
||||
Current link
|
||||
</NavItem>
|
||||
<NavItem id="default-link3" to="#default-link3" itemId={2}>
|
||||
Link 3
|
||||
</NavItem>
|
||||
<NavItem id="default-link4" to="#default-link4" itemId={3}>
|
||||
Link 4
|
||||
</NavItem>
|
||||
</NavList>
|
||||
</Nav>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
Loading…
Reference in a new issue