2020-08-04 12:59:41 +00:00
|
|
|
import {
|
|
|
|
Button,
|
2020-09-17 11:37:30 +00:00
|
|
|
ContextSelector,
|
|
|
|
ContextSelectorItem,
|
2023-02-09 12:53:39 +00:00
|
|
|
ContextSelectorItemProps,
|
2021-07-21 09:30:18 +00:00
|
|
|
Divider,
|
|
|
|
Dropdown,
|
|
|
|
DropdownItem,
|
|
|
|
DropdownToggle,
|
2021-04-08 19:20:35 +00:00
|
|
|
Label,
|
2022-10-03 20:22:37 +00:00
|
|
|
Spinner,
|
2021-07-21 09:30:18 +00:00
|
|
|
Split,
|
|
|
|
SplitItem,
|
2020-09-01 14:51:59 +00:00
|
|
|
} from "@patternfly/react-core";
|
2020-09-17 11:37:30 +00:00
|
|
|
import { CheckIcon } from "@patternfly/react-icons";
|
2023-02-09 12:53:39 +00:00
|
|
|
import { Fragment, useState } from "react";
|
2021-07-21 09:30:18 +00:00
|
|
|
import { useTranslation } from "react-i18next";
|
2023-02-09 12:53:39 +00:00
|
|
|
import { Link, To, useHref } from "react-router-dom";
|
2020-09-17 11:37:30 +00:00
|
|
|
|
2021-01-05 19:49:33 +00:00
|
|
|
import { useRealm } from "../../context/realm-context/RealmContext";
|
2021-11-11 16:04:04 +00:00
|
|
|
import { useRealms } from "../../context/RealmsContext";
|
2023-02-09 08:05:38 +00:00
|
|
|
import { useRecentRealms } from "../../context/RecentRealms";
|
2021-07-21 09:30:18 +00:00
|
|
|
import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
2021-09-07 11:19:50 +00:00
|
|
|
import { toDashboard } from "../../dashboard/routes/Dashboard";
|
2021-07-22 07:13:35 +00:00
|
|
|
import { toAddRealm } from "../../realm/routes/AddRealm";
|
2020-08-04 12:59:41 +00:00
|
|
|
|
2020-09-14 18:10:54 +00:00
|
|
|
import "./realm-selector.css";
|
2020-08-04 12:59:41 +00:00
|
|
|
|
2023-02-09 12:53:39 +00:00
|
|
|
type AddRealmProps = {
|
|
|
|
onClick: () => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
const AddRealm = ({ onClick }: AddRealmProps) => {
|
2023-02-07 14:21:58 +00:00
|
|
|
const { realm } = useRealm();
|
|
|
|
const { t } = useTranslation("common");
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Button
|
|
|
|
data-testid="add-realm"
|
|
|
|
component={(props) => <Link {...props} to={toAddRealm({ realm })} />}
|
2023-02-09 12:53:39 +00:00
|
|
|
onClick={onClick}
|
2023-02-07 14:21:58 +00:00
|
|
|
isBlock
|
|
|
|
>
|
|
|
|
{t("createRealm")}
|
|
|
|
</Button>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
type RealmTextProps = {
|
|
|
|
value: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
const RealmText = ({ value }: RealmTextProps) => {
|
|
|
|
const { realm } = useRealm();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Split className="keycloak__realm_selector__list-item-split">
|
|
|
|
<SplitItem isFilled>{value}</SplitItem>
|
|
|
|
<SplitItem>{value === realm && <CheckIcon />}</SplitItem>
|
|
|
|
</Split>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-02-09 12:53:39 +00:00
|
|
|
// We need to make all these props partial because of a bug in PatternFly.
|
|
|
|
// See: https://github.com/patternfly/patternfly-react/pull/8670
|
|
|
|
// TODO: Remove this partial when a fix has been released.
|
|
|
|
type ContextSelectorItemLinkProps = Partial<
|
|
|
|
Omit<ContextSelectorItemProps, "href">
|
|
|
|
> & {
|
|
|
|
to: To;
|
|
|
|
};
|
|
|
|
|
|
|
|
const ContextSelectorItemLink = ({
|
|
|
|
to,
|
|
|
|
...props
|
|
|
|
}: ContextSelectorItemLinkProps) => {
|
|
|
|
const href = useHref(to);
|
|
|
|
return <ContextSelectorItem {...props} href={href} />;
|
|
|
|
};
|
|
|
|
|
2021-05-03 16:44:47 +00:00
|
|
|
export const RealmSelector = () => {
|
2021-11-11 16:04:04 +00:00
|
|
|
const { realm } = useRealm();
|
2022-10-03 20:22:37 +00:00
|
|
|
const { realms, refresh } = useRealms();
|
2021-07-21 09:30:18 +00:00
|
|
|
const { whoAmI } = useWhoAmI();
|
2020-08-04 12:59:41 +00:00
|
|
|
const [open, setOpen] = useState(false);
|
2020-09-17 11:37:30 +00:00
|
|
|
const [search, setSearch] = useState("");
|
2020-10-29 18:56:52 +00:00
|
|
|
const { t } = useTranslation("common");
|
2023-02-09 08:05:38 +00:00
|
|
|
const recentRealms = useRecentRealms();
|
2023-02-07 14:21:58 +00:00
|
|
|
|
2023-02-09 08:05:38 +00:00
|
|
|
const all = recentRealms
|
2021-06-08 13:13:04 +00:00
|
|
|
.filter((r) => r !== realm)
|
2021-05-19 12:35:11 +00:00
|
|
|
.map((name) => {
|
|
|
|
return { name, used: true };
|
|
|
|
})
|
|
|
|
.concat(
|
|
|
|
realms
|
2023-02-09 08:05:38 +00:00
|
|
|
.filter((r) => !recentRealms.includes(r.realm!) || r.realm === realm)
|
2021-05-19 12:35:11 +00:00
|
|
|
.map((r) => {
|
|
|
|
return { name: r.realm!, used: false };
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
2023-02-07 14:21:58 +00:00
|
|
|
const filteredItems =
|
|
|
|
search === ""
|
|
|
|
? undefined
|
|
|
|
: all.filter((r) => r.name.toLowerCase().includes(search.toLowerCase()));
|
2021-05-19 12:35:11 +00:00
|
|
|
|
2022-10-03 20:22:37 +00:00
|
|
|
const dropdownItems =
|
|
|
|
realms.length !== 0
|
|
|
|
? realms.map((r) => (
|
|
|
|
<DropdownItem
|
|
|
|
key={`realm-dropdown-item-${r.realm}`}
|
2023-02-07 14:21:58 +00:00
|
|
|
component={
|
2023-02-09 12:53:39 +00:00
|
|
|
<Link
|
|
|
|
to={toDashboard({ realm: r.realm! })}
|
|
|
|
onClick={() => setOpen(false)}
|
|
|
|
>
|
2023-02-07 14:21:58 +00:00
|
|
|
<RealmText value={r.realm!} />
|
|
|
|
</Link>
|
|
|
|
}
|
|
|
|
/>
|
2022-10-03 20:22:37 +00:00
|
|
|
))
|
|
|
|
: [
|
|
|
|
<DropdownItem key="load">
|
|
|
|
Loading <Spinner size="sm" />
|
|
|
|
</DropdownItem>,
|
|
|
|
];
|
2020-09-04 18:16:11 +00:00
|
|
|
|
2023-02-07 14:21:58 +00:00
|
|
|
return realms.length > 5 ? (
|
|
|
|
<ContextSelector
|
|
|
|
data-testid="realmSelector"
|
|
|
|
toggleText={realm}
|
|
|
|
isOpen={open}
|
|
|
|
screenReaderLabel={realm}
|
|
|
|
onToggle={() => setOpen(!open)}
|
|
|
|
searchInputValue={search}
|
|
|
|
onSearchInputChange={(value) => setSearch(value)}
|
|
|
|
className="keycloak__realm_selector__context_selector"
|
|
|
|
footer={
|
|
|
|
whoAmI.canCreateRealm() && (
|
|
|
|
<ContextSelectorItem key="add">
|
2023-02-09 12:53:39 +00:00
|
|
|
<AddRealm onClick={() => setOpen(false)} />
|
2023-02-07 14:21:58 +00:00
|
|
|
</ContextSelectorItem>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
>
|
|
|
|
{(filteredItems || all).map((item) => (
|
2023-02-09 12:53:39 +00:00
|
|
|
<ContextSelectorItemLink
|
|
|
|
key={item.name}
|
|
|
|
to={toDashboard({ realm: item.name })}
|
|
|
|
onClick={() => setOpen(false)}
|
|
|
|
>
|
2023-02-07 14:21:58 +00:00
|
|
|
<RealmText value={item.name} />{" "}
|
|
|
|
{item.used && <Label>{t("recent")}</Label>}
|
2023-02-09 12:53:39 +00:00
|
|
|
</ContextSelectorItemLink>
|
2023-02-07 14:21:58 +00:00
|
|
|
))}
|
|
|
|
</ContextSelector>
|
|
|
|
) : (
|
|
|
|
<Dropdown
|
|
|
|
id="realm-select"
|
|
|
|
data-testid="realmSelector"
|
|
|
|
className="keycloak__realm_selector__dropdown"
|
|
|
|
isOpen={open}
|
|
|
|
toggle={
|
|
|
|
<DropdownToggle
|
|
|
|
data-testid="realmSelectorToggle"
|
|
|
|
onToggle={() => {
|
|
|
|
if (realms.length === 0) refresh();
|
|
|
|
setOpen(!open);
|
2020-09-17 11:37:30 +00:00
|
|
|
}}
|
2023-02-07 14:21:58 +00:00
|
|
|
className="keycloak__realm_selector_dropdown__toggle"
|
2020-08-04 12:59:41 +00:00
|
|
|
>
|
2023-02-07 14:21:58 +00:00
|
|
|
{realm}
|
|
|
|
</DropdownToggle>
|
|
|
|
}
|
|
|
|
dropdownItems={[
|
|
|
|
...dropdownItems,
|
|
|
|
<Fragment key="add-realm">
|
|
|
|
{whoAmI.canCreateRealm() && (
|
|
|
|
<>
|
|
|
|
<Divider key="divider" />
|
|
|
|
<DropdownItem key="add">
|
2023-02-09 12:53:39 +00:00
|
|
|
<AddRealm onClick={() => setOpen(false)} />
|
2023-02-07 14:21:58 +00:00
|
|
|
</DropdownItem>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</Fragment>,
|
|
|
|
]}
|
|
|
|
/>
|
2020-08-04 12:59:41 +00:00
|
|
|
);
|
|
|
|
};
|