Introduce 'useRequiredContext' utility function (#882)
This commit is contained in:
parent
d8d230557e
commit
41a0923bad
28 changed files with 393 additions and 258 deletions
94
package-lock.json
generated
94
package-lock.json
generated
|
@ -58,6 +58,7 @@
|
|||
"postcss-import": "^14.0.2",
|
||||
"prettier": "^2.3.2",
|
||||
"snowpack": "^3.8.2",
|
||||
"ts-jest": "^26.5.6",
|
||||
"ts-node": "^10.1.0",
|
||||
"typescript": "4.2.4"
|
||||
},
|
||||
|
@ -4789,6 +4790,18 @@
|
|||
"url": "https://opencollective.com/browserslist"
|
||||
}
|
||||
},
|
||||
"node_modules/bs-logger": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
|
||||
"integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fast-json-stable-stringify": "2.x"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/bser": {
|
||||
"version": "2.1.1",
|
||||
"integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
|
||||
|
@ -16097,6 +16110,49 @@
|
|||
"integrity": "sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ts-jest": {
|
||||
"version": "26.5.6",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz",
|
||||
"integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"bs-logger": "0.x",
|
||||
"buffer-from": "1.x",
|
||||
"fast-json-stable-stringify": "2.x",
|
||||
"jest-util": "^26.1.0",
|
||||
"json5": "2.x",
|
||||
"lodash": "4.x",
|
||||
"make-error": "1.x",
|
||||
"mkdirp": "1.x",
|
||||
"semver": "7.x",
|
||||
"yargs-parser": "20.x"
|
||||
},
|
||||
"bin": {
|
||||
"ts-jest": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jest": ">=26 <27",
|
||||
"typescript": ">=3.8 <5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.1.0",
|
||||
"integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==",
|
||||
|
@ -20470,6 +20526,15 @@
|
|||
"node-releases": "^1.1.71"
|
||||
}
|
||||
},
|
||||
"bs-logger": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
|
||||
"integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-json-stable-stringify": "2.x"
|
||||
}
|
||||
},
|
||||
"bser": {
|
||||
"version": "2.1.1",
|
||||
"integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
|
||||
|
@ -28974,6 +29039,35 @@
|
|||
"integrity": "sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g==",
|
||||
"dev": true
|
||||
},
|
||||
"ts-jest": {
|
||||
"version": "26.5.6",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz",
|
||||
"integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bs-logger": "0.x",
|
||||
"buffer-from": "1.x",
|
||||
"fast-json-stable-stringify": "2.x",
|
||||
"jest-util": "^26.1.0",
|
||||
"json5": "2.x",
|
||||
"lodash": "4.x",
|
||||
"make-error": "1.x",
|
||||
"mkdirp": "1.x",
|
||||
"semver": "7.x",
|
||||
"yargs-parser": "20.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "10.1.0",
|
||||
"integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==",
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
"postcss-import": "^14.0.2",
|
||||
"prettier": "^2.3.2",
|
||||
"snowpack": "^3.8.2",
|
||||
"ts-jest": "^26.5.6",
|
||||
"ts-node": "^10.1.0",
|
||||
"typescript": "4.2.4"
|
||||
},
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Avatar,
|
||||
Brand,
|
||||
|
@ -10,14 +8,16 @@ import {
|
|||
KebabToggle,
|
||||
PageHeader,
|
||||
PageHeaderTools,
|
||||
PageHeaderToolsItem,
|
||||
PageHeaderToolsGroup,
|
||||
PageHeaderToolsItem,
|
||||
} from "@patternfly/react-core";
|
||||
import { HelpIcon } from "@patternfly/react-icons";
|
||||
import { WhoAmIContext } from "./context/whoami/WhoAmI";
|
||||
import { HelpContext, HelpHeader } from "./components/help-enabler/HelpHeader";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, useHistory } from "react-router-dom";
|
||||
import { HelpHeader, useHelp } from "./components/help-enabler/HelpHeader";
|
||||
import { useAdminClient } from "./context/auth/AdminClient";
|
||||
import { useWhoAmI } from "./context/whoami/WhoAmI";
|
||||
import environment from "./environment";
|
||||
|
||||
export const Header = () => {
|
||||
|
@ -73,7 +73,7 @@ export const Header = () => {
|
|||
|
||||
const HelpDropdownItem = () => {
|
||||
const { t } = useTranslation();
|
||||
const { enabled, toggleHelp } = useContext(HelpContext);
|
||||
const { enabled, toggleHelp } = useHelp();
|
||||
return (
|
||||
<DropdownItem icon={<HelpIcon />} onClick={toggleHelp}>
|
||||
{enabled ? t("helpEnabled") : t("helpDisabled")}
|
||||
|
@ -155,7 +155,7 @@ export const Header = () => {
|
|||
};
|
||||
|
||||
const UserDropdown = () => {
|
||||
const { whoAmI } = useContext(WhoAmIContext);
|
||||
const { whoAmI } = useWhoAmI();
|
||||
const [isDropdownOpen, setDropdownOpen] = useState(false);
|
||||
|
||||
const onDropdownToggle = () => {
|
||||
|
|
|
@ -1,36 +1,34 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
Divider,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectVariant,
|
||||
TextInput,
|
||||
SelectOption,
|
||||
ActionGroup,
|
||||
Button,
|
||||
SelectGroup,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Split,
|
||||
SplitItem,
|
||||
Divider,
|
||||
TextInput,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
|
||||
import type ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
|
||||
import type ProtocolMapperRepresentation from "keycloak-admin/lib/defs/protocolMapperRepresentation";
|
||||
import type RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
|
||||
import React, { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { RealmContext } from "../../context/realm-context/RealmContext";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
|
||||
import { ViewHeader } from "../../components/view-header/ViewHeader";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { ViewHeader } from "../../components/view-header/ViewHeader";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
|
||||
export const RoleMappingForm = () => {
|
||||
const { realm } = useContext(RealmContext);
|
||||
const { realm } = useRealm();
|
||||
const adminClient = useAdminClient();
|
||||
const history = useHistory();
|
||||
const { addAlert } = useAlerts();
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
ClipboardCopy,
|
||||
EmptyState,
|
||||
|
@ -25,19 +23,19 @@ import {
|
|||
} from "@patternfly/react-core";
|
||||
import { QuestionCircleIcon } from "@patternfly/react-icons";
|
||||
import type ClientScopeRepresentation from "keycloak-admin/lib/defs/clientScopeRepresentation";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import type RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
|
||||
import type ProtocolMapperRepresentation from "keycloak-admin/lib/defs/protocolMapperRepresentation";
|
||||
import type RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
|
||||
import type { ProtocolMapperTypeRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
|
||||
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { RealmContext } from "../../context/realm-context/RealmContext";
|
||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHelp } from "../../components/help-enabler/HelpHeader";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
|
||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import "./evaluate.css";
|
||||
import { HelpContext } from "../../components/help-enabler/HelpHeader";
|
||||
|
||||
export type EvaluateScopesProps = {
|
||||
clientId: string;
|
||||
|
@ -114,9 +112,9 @@ const EffectiveRoles = ({
|
|||
export const EvaluateScopes = ({ clientId, protocol }: EvaluateScopesProps) => {
|
||||
const prefix = "openid";
|
||||
const { t } = useTranslation("clients");
|
||||
const { enabled } = useContext(HelpContext);
|
||||
const { enabled } = useHelp();
|
||||
const adminClient = useAdminClient();
|
||||
const { realm } = useContext(RealmContext);
|
||||
const { realm } = useRealm();
|
||||
const mapperTypes = useServerInfo().protocolMapperTypes![protocol];
|
||||
|
||||
const [selectableScopes, setSelectableScopes] = useState<
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState, createContext, ReactNode, useContext } from "react";
|
||||
import { AlertType, AlertPanel } from "./AlertPanel";
|
||||
import { AlertVariant } from "@patternfly/react-core";
|
||||
import React, { createContext, ReactNode, useState } from "react";
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
import { AlertPanel, AlertType } from "./AlertPanel";
|
||||
|
||||
type AlertProps = {
|
||||
addAlert: (
|
||||
|
@ -10,11 +11,9 @@ type AlertProps = {
|
|||
) => void;
|
||||
};
|
||||
|
||||
export const AlertContext = createContext<AlertProps>({
|
||||
addAlert: () => {},
|
||||
});
|
||||
export const AlertContext = createContext<AlertProps | undefined>(undefined);
|
||||
|
||||
export const useAlerts = () => useContext(AlertContext);
|
||||
export const useAlerts = () => useRequiredContext(AlertContext);
|
||||
|
||||
export const AlertProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [alerts, setAlerts] = useState<AlertType[]>([]);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import React, { useState, useContext } from "react";
|
||||
import {
|
||||
Alert,
|
||||
AlertVariant,
|
||||
|
@ -13,13 +12,13 @@ import {
|
|||
TextArea,
|
||||
} from "@patternfly/react-core";
|
||||
import FileSaver from "file-saver";
|
||||
|
||||
import { ConfirmDialogModal } from "../confirm-dialog/ConfirmDialog";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { HelpContext } from "../help-enabler/HelpHeader";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { ConfirmDialogModal } from "../confirm-dialog/ConfirmDialog";
|
||||
import { useHelp } from "../help-enabler/HelpHeader";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
|
||||
type DownloadDialogProps = {
|
||||
id: string;
|
||||
|
@ -36,7 +35,7 @@ export const DownloadDialog = ({
|
|||
}: DownloadDialogProps) => {
|
||||
const adminClient = useAdminClient();
|
||||
const { t } = useTranslation("common");
|
||||
const { enabled } = useContext(HelpContext);
|
||||
const { enabled } = useHelp();
|
||||
const serverInfo = useServerInfo();
|
||||
|
||||
const configFormats = serverInfo.clientInstallations![protocol];
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import React, { useState, useContext, ReactNode, createContext } from "react";
|
||||
import {
|
||||
Divider,
|
||||
Dropdown,
|
||||
|
@ -9,9 +8,10 @@ import {
|
|||
Switch,
|
||||
TextContent,
|
||||
} from "@patternfly/react-core";
|
||||
import { ExternalLinkAltIcon, HelpIcon } from "@patternfly/react-icons";
|
||||
import React, { createContext, ReactNode, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HelpIcon, ExternalLinkAltIcon } from "@patternfly/react-icons";
|
||||
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
import "./help-header.css";
|
||||
|
||||
type HelpProps = {
|
||||
|
@ -23,10 +23,11 @@ type HelpContextProps = {
|
|||
toggleHelp: () => void;
|
||||
};
|
||||
|
||||
export const HelpContext = createContext<HelpContextProps>({
|
||||
enabled: true,
|
||||
toggleHelp: () => {},
|
||||
});
|
||||
export const HelpContext = createContext<HelpContextProps | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export const useHelp = () => useRequiredContext(HelpContext);
|
||||
|
||||
export const Help = ({ children }: HelpProps) => {
|
||||
const [enabled, setHelp] = useState(true);
|
||||
|
@ -43,7 +44,7 @@ export const Help = ({ children }: HelpProps) => {
|
|||
|
||||
export const HelpHeader = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const help = useContext(HelpContext);
|
||||
const help = useHelp();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const dropdownItems = [
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React, { isValidElement, ReactNode, useContext } from "react";
|
||||
import { Popover } from "@patternfly/react-core";
|
||||
import { HelpIcon } from "@patternfly/react-icons";
|
||||
import React, { isValidElement, ReactNode } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HelpContext } from "./HelpHeader";
|
||||
import { useHelp } from "./HelpHeader";
|
||||
|
||||
type HelpItemProps = {
|
||||
helpText: string | ReactNode;
|
||||
|
@ -22,7 +22,7 @@ export const HelpItem = ({
|
|||
unWrap = false,
|
||||
}: HelpItemProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { enabled } = useContext(HelpContext);
|
||||
const { enabled } = useHelp();
|
||||
return (
|
||||
<>
|
||||
{enabled && (
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
import React, { useState, useContext, ReactElement, useMemo } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownToggle,
|
||||
DropdownItem,
|
||||
Button,
|
||||
Divider,
|
||||
SplitItem,
|
||||
Split,
|
||||
ContextSelector,
|
||||
ContextSelectorItem,
|
||||
Divider,
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
DropdownToggle,
|
||||
Label,
|
||||
Split,
|
||||
SplitItem,
|
||||
} from "@patternfly/react-core";
|
||||
import { CheckIcon } from "@patternfly/react-icons";
|
||||
import React, { ReactElement, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import { toUpperCase } from "../../util";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { WhoAmIContext } from "../../context/whoami/WhoAmI";
|
||||
import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
||||
import { toUpperCase } from "../../util";
|
||||
import { RecentUsed } from "./recent-used";
|
||||
|
||||
import "./realm-selector.css";
|
||||
|
||||
export const RealmSelector = () => {
|
||||
const { realm, setRealm, realms } = useRealm();
|
||||
const { whoAmI } = useContext(WhoAmIContext);
|
||||
const { whoAmI } = useWhoAmI();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [search, setSearch] = useState("");
|
||||
const history = useHistory();
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
import React, { ReactElement, ReactNode, useContext, useState } from "react";
|
||||
import {
|
||||
Text,
|
||||
PageSection,
|
||||
TextContent,
|
||||
Badge,
|
||||
Divider,
|
||||
Dropdown,
|
||||
DropdownPosition,
|
||||
DropdownToggle,
|
||||
Level,
|
||||
LevelItem,
|
||||
PageSection,
|
||||
Switch,
|
||||
Text,
|
||||
TextContent,
|
||||
Toolbar,
|
||||
ToolbarContent,
|
||||
ToolbarItem,
|
||||
Badge,
|
||||
Dropdown,
|
||||
DropdownToggle,
|
||||
DropdownPosition,
|
||||
} from "@patternfly/react-core";
|
||||
import { HelpContext } from "../help-enabler/HelpHeader";
|
||||
import React, { ReactElement, ReactNode, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
FormattedLink,
|
||||
FormattedLinkProps,
|
||||
} from "../external-link/FormattedLink";
|
||||
import { useHelp } from "../help-enabler/HelpHeader";
|
||||
import { HelpItem } from "../help-enabler/HelpItem";
|
||||
|
||||
export type ViewHeaderProps = {
|
||||
|
@ -56,7 +56,7 @@ export const ViewHeader = ({
|
|||
helpTextKey,
|
||||
}: ViewHeaderProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { enabled } = useContext(HelpContext);
|
||||
const { enabled } = useHelp();
|
||||
const [isDropdownOpen, setDropdownOpen] = useState(false);
|
||||
const [isLowerDropdownOpen, setIsLowerDropdownOpen] = useState(false);
|
||||
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
|
||||
|
||||
import { RealmContext } from "../../context/realm-context/RealmContext";
|
||||
import { WhoAmIContext } from "../../context/whoami/WhoAmI";
|
||||
import React, { createContext, useEffect, useState } from "react";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
|
||||
type AccessContextProps = {
|
||||
hasAccess: (...types: AccessType[]) => boolean;
|
||||
hasSomeAccess: (...types: AccessType[]) => boolean;
|
||||
};
|
||||
|
||||
export const AccessContext = createContext<AccessContextProps>({
|
||||
hasAccess: () => false,
|
||||
hasSomeAccess: () => false,
|
||||
});
|
||||
export const AccessContext = createContext<AccessContextProps | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export const useAccess = () => useContext(AccessContext);
|
||||
export const useAccess = () => useRequiredContext(AccessContext);
|
||||
|
||||
type AccessProviderProps = { children: React.ReactNode };
|
||||
export const AccessContextProvider = ({ children }: AccessProviderProps) => {
|
||||
const { whoAmI } = useContext(WhoAmIContext);
|
||||
const { realm } = useContext(RealmContext);
|
||||
const { whoAmI } = useWhoAmI();
|
||||
const { realm } = useRealm();
|
||||
const [access, setAccess] = useState<readonly AccessType[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import { createContext, DependencyList, useContext, useEffect } from "react";
|
||||
import axios from "axios";
|
||||
|
||||
import type KeycloakAdminClient from "keycloak-admin";
|
||||
import { createContext, DependencyList, useEffect } from "react";
|
||||
import { useErrorHandler } from "react-error-boundary";
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
|
||||
export const AdminClient = createContext<KeycloakAdminClient | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export const useAdminClient = () => {
|
||||
return useContext(AdminClient)!;
|
||||
};
|
||||
export const useAdminClient = () => useRequiredContext(AdminClient);
|
||||
|
||||
/**
|
||||
* Util function to only set the state when the component is still mounted.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import _ from "lodash";
|
||||
|
||||
import type RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
|
||||
import _ from "lodash";
|
||||
import React, { useState } from "react";
|
||||
import { RecentUsed } from "../../components/realm-selector/recent-used";
|
||||
import { useAdminClient, useFetch } from "../auth/AdminClient";
|
||||
import environment from "../../environment";
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
import { useAdminClient, useFetch } from "../auth/AdminClient";
|
||||
|
||||
type RealmContextType = {
|
||||
realm: string;
|
||||
|
@ -13,12 +13,9 @@ type RealmContextType = {
|
|||
refresh: () => Promise<void>;
|
||||
};
|
||||
|
||||
export const RealmContext = React.createContext<RealmContextType>({
|
||||
realm: "",
|
||||
setRealm: () => {},
|
||||
realms: [],
|
||||
refresh: () => Promise.resolve(),
|
||||
});
|
||||
export const RealmContext = React.createContext<RealmContextType | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
type RealmContextProviderProps = { children: React.ReactNode };
|
||||
|
||||
|
@ -70,4 +67,4 @@ export const RealmContextProvider = ({
|
|||
);
|
||||
};
|
||||
|
||||
export const useRealm = () => useContext(RealmContext);
|
||||
export const useRealm = () => useRequiredContext(RealmContext);
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React, { createContext, ReactNode, useContext } from "react";
|
||||
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
|
||||
|
||||
import { sortProviders } from "../../util";
|
||||
import React, { createContext, ReactNode } from "react";
|
||||
import { DataLoader } from "../../components/data-loader/DataLoader";
|
||||
import { sortProviders } from "../../util";
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
import { useAdminClient } from "../auth/AdminClient";
|
||||
|
||||
export const ServerInfoContext = createContext<ServerInfoRepresentation>(
|
||||
{} as ServerInfoRepresentation
|
||||
);
|
||||
export const ServerInfoContext = createContext<
|
||||
ServerInfoRepresentation | undefined
|
||||
>(undefined);
|
||||
|
||||
export const useServerInfo = () => useContext(ServerInfoContext);
|
||||
export const useServerInfo = () => useRequiredContext(ServerInfoContext);
|
||||
|
||||
export const useLoginProviders = () => {
|
||||
return sortProviders(useServerInfo().providers!["login-protocol"].providers);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React, { useState } from "react";
|
||||
import i18n from "../../i18n";
|
||||
|
||||
import type WhoAmIRepresentation from "keycloak-admin/lib/defs/whoAmIRepresentation";
|
||||
import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
|
||||
import React, { useState } from "react";
|
||||
import i18n from "../../i18n";
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
import { useAdminClient, useFetch } from "../auth/AdminClient";
|
||||
|
||||
export class WhoAmI {
|
||||
|
@ -44,10 +44,11 @@ type WhoAmIProps = {
|
|||
whoAmI: WhoAmI;
|
||||
};
|
||||
|
||||
export const WhoAmIContext = React.createContext<WhoAmIProps>({
|
||||
refresh: () => {},
|
||||
whoAmI: new WhoAmI(),
|
||||
});
|
||||
export const WhoAmIContext = React.createContext<WhoAmIProps | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export const useWhoAmI = () => useRequiredContext(WhoAmIContext);
|
||||
|
||||
type WhoAmIProviderProps = { children: React.ReactNode };
|
||||
export const WhoAmIContextProvider = ({ children }: WhoAmIProviderProps) => {
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import React, { ReactNode, useContext, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
|
@ -8,11 +5,6 @@ import {
|
|||
ToolbarItem,
|
||||
Tooltip,
|
||||
} from "@patternfly/react-core";
|
||||
import moment from "moment";
|
||||
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { RealmContext } from "../context/realm-context/RealmContext";
|
||||
import {
|
||||
cellWidth,
|
||||
Table,
|
||||
|
@ -21,7 +13,14 @@ import {
|
|||
TableVariant,
|
||||
} from "@patternfly/react-table";
|
||||
import type AdminEventRepresentation from "keycloak-admin/lib/defs/adminEventRepresentation";
|
||||
import moment from "moment";
|
||||
import React, { ReactNode, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
||||
type DisplayDialogProps = {
|
||||
titleKey: string;
|
||||
|
@ -67,7 +66,7 @@ const Truncate = ({
|
|||
export const AdminEvents = () => {
|
||||
const { t } = useTranslation("events");
|
||||
const adminClient = useAdminClient();
|
||||
const { realm } = useContext(RealmContext);
|
||||
const { realm } = useRealm();
|
||||
|
||||
const [key, setKey] = useState(0);
|
||||
const refresh = () => setKey(new Date().getTime());
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import moment from "moment";
|
||||
import {
|
||||
Button,
|
||||
DescriptionList,
|
||||
|
@ -14,24 +10,26 @@ import {
|
|||
ToolbarItem,
|
||||
Tooltip,
|
||||
} from "@patternfly/react-core";
|
||||
import { cellWidth, expandable } from "@patternfly/react-table";
|
||||
import { CheckCircleIcon, WarningTriangleIcon } from "@patternfly/react-icons";
|
||||
import { cellWidth, expandable } from "@patternfly/react-table";
|
||||
import type EventRepresentation from "keycloak-admin/lib/defs/eventRepresentation";
|
||||
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { RealmContext } from "../context/realm-context/RealmContext";
|
||||
import { AdminEvents } from "./AdminEvents";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import moment from "moment";
|
||||
import React, { useState } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { AdminEvents } from "./AdminEvents";
|
||||
import "./events-section.css";
|
||||
|
||||
export const EventsSection = () => {
|
||||
const { t } = useTranslation("events");
|
||||
const adminClient = useAdminClient();
|
||||
const { realm } = useContext(RealmContext);
|
||||
const { realm } = useRealm();
|
||||
|
||||
const [key, setKey] = useState(0);
|
||||
const refresh = () => setKey(new Date().getTime());
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { createContext, ReactNode, useContext, useState } from "react";
|
||||
import type GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation";
|
||||
import React, { createContext, ReactNode, useState } from "react";
|
||||
import useRequiredContext from "../utils/useRequiredContext";
|
||||
|
||||
type SubGroupsProps = {
|
||||
subGroups: GroupRepresentation[];
|
||||
|
@ -9,15 +10,7 @@ type SubGroupsProps = {
|
|||
currentGroup: () => GroupRepresentation;
|
||||
};
|
||||
|
||||
const SubGroupContext = createContext<SubGroupsProps>({
|
||||
subGroups: [],
|
||||
setSubGroups: () => {},
|
||||
clear: () => {},
|
||||
remove: () => {},
|
||||
currentGroup: () => {
|
||||
return {};
|
||||
},
|
||||
});
|
||||
const SubGroupContext = createContext<SubGroupsProps | undefined>(undefined);
|
||||
|
||||
export const SubGroups = ({ children }: { children: ReactNode }) => {
|
||||
const [subGroups, setSubGroups] = useState<GroupRepresentation[]>([]);
|
||||
|
@ -37,4 +30,4 @@ export const SubGroups = ({ children }: { children: ReactNode }) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const useSubGroups = () => useContext(SubGroupContext);
|
||||
export const useSubGroups = () => useRequiredContext(SubGroupContext);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useContext } from "react";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, PageSection, Popover } from "@patternfly/react-core";
|
||||
import { QuestionCircleIcon } from "@patternfly/react-icons";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
import { useHelp } from "../components/help-enabler/HelpHeader";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { upperCaseFormatter, emptyFormatter } from "../util";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { QuestionCircleIcon } from "@patternfly/react-icons";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { HelpContext } from "../components/help-enabler/HelpHeader";
|
||||
import { emptyFormatter, upperCaseFormatter } from "../util";
|
||||
|
||||
export const UsersInRoleTab = () => {
|
||||
const history = useHistory();
|
||||
|
@ -30,7 +30,7 @@ export const UsersInRoleTab = () => {
|
|||
return usersWithRole || [];
|
||||
};
|
||||
|
||||
const { enabled } = useContext(HelpContext);
|
||||
const { enabled } = useHelp();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
|
@ -11,20 +8,21 @@ import {
|
|||
Switch,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { FormAccess } from "../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { FormPanel } from "../components/scroll-form/FormPanel";
|
||||
import { emailRegexPattern } from "../util";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
||||
import "./RealmSettingsSection.css";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import { WhoAmIContext } from "../context/whoami/WhoAmI";
|
||||
import { useWhoAmI } from "../context/whoami/WhoAmI";
|
||||
import { emailRegexPattern } from "../util";
|
||||
import { AddUserEmailModal } from "./AddUserEmailModal";
|
||||
import "./RealmSettingsSection.css";
|
||||
|
||||
type RealmSettingsEmailTabProps = {
|
||||
realm: RealmRepresentation;
|
||||
|
@ -39,7 +37,7 @@ export const RealmSettingsEmailTab = ({
|
|||
const adminClient = useAdminClient();
|
||||
const { realm: realmName } = useRealm();
|
||||
const { addAlert } = useAlerts();
|
||||
const { whoAmI } = useContext(WhoAmIContext);
|
||||
const { whoAmI } = useWhoAmI();
|
||||
|
||||
const [realm, setRealm] = useState(initialRealm);
|
||||
const [userEmailModalOpen, setUserEmailModalOpen] = useState(false);
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
import React, { useEffect, useState, useContext } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||
import {
|
||||
AlertVariant,
|
||||
Breadcrumb,
|
||||
|
@ -14,30 +10,33 @@ import {
|
|||
Tabs,
|
||||
TabTitleText,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import type RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
|
||||
import { toUpperCase } from "../util";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||
import { RealmSettingsLoginTab } from "./LoginTab";
|
||||
import { RealmSettingsGeneralTab } from "./GeneralTab";
|
||||
import { PartialImportDialog } from "./PartialImport";
|
||||
import { RealmSettingsThemesTab } from "./ThemesTab";
|
||||
import { RealmSettingsEmailTab } from "./EmailTab";
|
||||
import { KeysListTab } from "./KeysListTab";
|
||||
import { EventsTab } from "./event-config/EventsTab";
|
||||
import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { KeysProvidersTab } from "./KeysProvidersTab";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
//import { LocalizationTab } from "./LocalizationTab";
|
||||
import { WhoAmIContext } from "../context/whoami/WhoAmI";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import { useWhoAmI } from "../context/whoami/WhoAmI";
|
||||
import { toUpperCase } from "../util";
|
||||
import { RealmSettingsEmailTab } from "./EmailTab";
|
||||
import { EventsTab } from "./event-config/EventsTab";
|
||||
import { RealmSettingsGeneralTab } from "./GeneralTab";
|
||||
import { KeysListTab } from "./KeysListTab";
|
||||
import { KeysProvidersTab } from "./KeysProvidersTab";
|
||||
import { RealmSettingsLoginTab } from "./LoginTab";
|
||||
import { PartialImportDialog } from "./PartialImport";
|
||||
import { SecurityDefences } from "./security-defences/SecurityDefences";
|
||||
import { RealmSettingsSessionsTab } from "./SessionsTab";
|
||||
import { RealmSettingsThemesTab } from "./ThemesTab";
|
||||
|
||||
type RealmSettingsHeaderProps = {
|
||||
onChange: (value: boolean) => void;
|
||||
|
@ -124,9 +123,7 @@ const RealmSettingsHeader = ({
|
|||
>
|
||||
{t("partialImport")}
|
||||
</DropdownItem>,
|
||||
<DropdownItem key="export" onClick={() => {}}>
|
||||
{t("partialExport")}
|
||||
</DropdownItem>,
|
||||
<DropdownItem key="export">{t("partialExport")}</DropdownItem>,
|
||||
<DropdownSeparator key="separator" />,
|
||||
<DropdownItem key="delete" onClick={toggleDeleteDialog}>
|
||||
{t("common:delete")}
|
||||
|
@ -159,7 +156,7 @@ export const RealmSettingsSection = () => {
|
|||
const [realmComponents, setRealmComponents] =
|
||||
useState<ComponentRepresentation[]>();
|
||||
const [currentUser, setCurrentUser] = useState<UserRepresentation>();
|
||||
const { whoAmI } = useContext(WhoAmIContext);
|
||||
const { whoAmI } = useWhoAmI();
|
||||
|
||||
const kpComponentTypes =
|
||||
useServerInfo().componentTypes!["org.keycloak.keys.KeyProvider"];
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
import React, { useContext } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
PageSection,
|
||||
FormGroup,
|
||||
TextInput,
|
||||
Switch,
|
||||
ActionGroup,
|
||||
Button,
|
||||
AlertVariant,
|
||||
Button,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Switch,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { JsonFileUpload } from "../../components/json-file-upload/JsonFileUpload";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { ViewHeader } from "../../components/view-header/ViewHeader";
|
||||
import type RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { WhoAmIContext } from "../../context/whoami/WhoAmI";
|
||||
import React from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { JsonFileUpload } from "../../components/json-file-upload/JsonFileUpload";
|
||||
import { ViewHeader } from "../../components/view-header/ViewHeader";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
||||
|
||||
export const NewRealmForm = () => {
|
||||
const { t } = useTranslation("realm");
|
||||
const history = useHistory();
|
||||
const { refresh } = useContext(WhoAmIContext);
|
||||
const { refresh } = useWhoAmI();
|
||||
const { refresh: realmRefresh } = useRealm();
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert } = useAlerts();
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import { useHistory, useRouteMatch } from "react-router-dom";
|
||||
import {
|
||||
AlertVariant,
|
||||
ButtonVariant,
|
||||
|
@ -15,17 +13,17 @@ import {
|
|||
TextContent,
|
||||
TextVariants,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import { KeycloakCard } from "../components/keycloak-card/KeycloakCard";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { DatabaseIcon } from "@patternfly/react-icons";
|
||||
import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RealmContext } from "../context/realm-context/RealmContext";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useHistory, useRouteMatch } from "react-router-dom";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
|
||||
import { KeycloakCard } from "../components/keycloak-card/KeycloakCard";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import "./user-federation.css";
|
||||
|
||||
export const UserFederationSection = () => {
|
||||
|
@ -33,7 +31,7 @@ export const UserFederationSection = () => {
|
|||
useState<ComponentRepresentation[]>();
|
||||
const { addAlert } = useAlerts();
|
||||
const { t } = useTranslation("user-federation");
|
||||
const { realm } = useContext(RealmContext);
|
||||
const { realm } = useRealm();
|
||||
const adminClient = useAdminClient();
|
||||
const [key, setKey] = useState(0);
|
||||
const refresh = () => setKey(new Date().getTime());
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
|
@ -8,20 +5,23 @@ import {
|
|||
Checkbox,
|
||||
Popover,
|
||||
} from "@patternfly/react-core";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { QuestionCircleIcon } from "@patternfly/react-icons";
|
||||
import { cellWidth } from "@patternfly/react-table";
|
||||
import type GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import _ from "lodash";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { emptyFormatter } from "../util";
|
||||
import { useFetch, useAdminClient } from "../context/auth/AdminClient";
|
||||
import type GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation";
|
||||
import { cellWidth } from "@patternfly/react-table";
|
||||
import _ from "lodash";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
import { GroupPickerDialog } from "../components/group/GroupPickerDialog";
|
||||
import { HelpContext } from "../components/help-enabler/HelpHeader";
|
||||
import { QuestionCircleIcon } from "@patternfly/react-icons";
|
||||
import { GroupPath } from "../components/group/GroupPath";
|
||||
import { GroupPickerDialog } from "../components/group/GroupPickerDialog";
|
||||
import { useHelp } from "../components/help-enabler/HelpHeader";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { emptyFormatter } from "../util";
|
||||
|
||||
export type UserFormProps = {
|
||||
username?: string;
|
||||
|
@ -52,7 +52,7 @@ export const UserGroups = () => {
|
|||
>([]);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { enabled } = useContext(HelpContext);
|
||||
const { enabled } = useHelp();
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
@ -295,7 +295,6 @@ export const UserGroups = () => {
|
|||
ariaLabelKey="roles:roleList"
|
||||
searchPlaceholderKey="groups:searchGroup"
|
||||
canSelectAll
|
||||
onSelect={() => {}}
|
||||
toolbarItem={
|
||||
<>
|
||||
<Button
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, useHistory, useRouteMatch } from "react-router-dom";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
|
@ -16,17 +13,18 @@ import {
|
|||
WarningTriangleIcon,
|
||||
} from "@patternfly/react-icons";
|
||||
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
||||
|
||||
import { useFetch, useAdminClient } from "../context/auth/AdminClient";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, useHistory, useRouteMatch } from "react-router-dom";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { RealmContext } from "../context/realm-context/RealmContext";
|
||||
import { SearchUser } from "./SearchUser";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { emptyFormatter } from "../util";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { emptyFormatter } from "../util";
|
||||
import { SearchUser } from "./SearchUser";
|
||||
import "./user-section.css";
|
||||
|
||||
type BruteUser = UserRepresentation & {
|
||||
|
@ -37,7 +35,7 @@ export const UsersSection = () => {
|
|||
const { t } = useTranslation("users");
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert } = useAlerts();
|
||||
const { realm: realmName } = useContext(RealmContext);
|
||||
const { realm: realmName } = useRealm();
|
||||
const history = useHistory();
|
||||
const { url } = useRouteMatch();
|
||||
const [listUsers, setListUsers] = useState(false);
|
||||
|
|
47
src/utils/useRequiredContext.test.ts
Normal file
47
src/utils/useRequiredContext.test.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import type { Context } from "react";
|
||||
import { useContext } from "react";
|
||||
import { mocked } from "ts-jest/utils";
|
||||
import useRequiredContext from "./useRequiredContext";
|
||||
|
||||
jest.mock("react");
|
||||
|
||||
const useContextMock = mocked(useContext);
|
||||
|
||||
describe("useRequiredContext", () => {
|
||||
beforeEach(() => {
|
||||
useContextMock.mockReset();
|
||||
});
|
||||
|
||||
it("resolves the context", () => {
|
||||
const context = {} as Context<unknown>;
|
||||
const resolved = "FakeValue";
|
||||
|
||||
useContextMock.mockReturnValue(resolved);
|
||||
|
||||
expect(useRequiredContext(context)).toEqual(resolved);
|
||||
});
|
||||
|
||||
it("throws if a named context cannot be resolved", () => {
|
||||
const displayName = "FakeDisplayName";
|
||||
const context = { displayName } as Context<unknown>;
|
||||
const expected = `No provider found for the '${displayName}' context, make sure it is included in your component hierarchy.`;
|
||||
|
||||
useContextMock.mockReturnValue(undefined);
|
||||
expect(() => useRequiredContext(context)).toThrow(expected);
|
||||
|
||||
useContextMock.mockReturnValue(null);
|
||||
expect(() => useRequiredContext(context)).toThrow(expected);
|
||||
});
|
||||
|
||||
it("throws if an unnamed context cannot be resolved", () => {
|
||||
const context = {} as Context<unknown>;
|
||||
const expected =
|
||||
"No provider found for an unknown context, make sure it is included in your component hierarchy.";
|
||||
|
||||
useContextMock.mockReturnValue(undefined);
|
||||
expect(() => useRequiredContext(context)).toThrow(expected);
|
||||
|
||||
useContextMock.mockReturnValue(null);
|
||||
expect(() => useRequiredContext(context)).toThrow(expected);
|
||||
});
|
||||
});
|
25
src/utils/useRequiredContext.ts
Normal file
25
src/utils/useRequiredContext.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { useContext } from "react";
|
||||
import type { Context } from "react";
|
||||
|
||||
/**
|
||||
* Passes the call to `useContext` and throw an exception if the resolved value is either `null` or `undefined`.
|
||||
* Can be used for contexts that are required and should always have a non nullable value.
|
||||
*
|
||||
* @param context The context to pass to `useContext`
|
||||
* @returns
|
||||
*/
|
||||
export default function useRequiredContext<T>(
|
||||
context: Context<T>
|
||||
): NonNullable<T> {
|
||||
const resolved = useContext(context);
|
||||
|
||||
if (resolved !== undefined && resolved !== null) {
|
||||
return resolved as NonNullable<T>;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`No provider found for ${
|
||||
context.displayName ? `the '${context.displayName}'` : "an unknown"
|
||||
} context, make sure it is included in your component hierarchy.`
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue