Add display names to contexts (#3032)

This commit is contained in:
Jon Koops 2022-08-03 15:15:04 +02:00 committed by GitHub
parent a6fd2cabfa
commit e363fb68b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 75 additions and 45 deletions

View file

@ -21,7 +21,7 @@ import { SubGroups } from "./groups/SubGroupsContext";
import { RealmsProvider } from "./context/RealmsContext";
import { RealmContextProvider } from "./context/realm-context/RealmContext";
import { ErrorRenderer } from "./components/error/ErrorRenderer";
import { AdminClient } from "./context/auth/AdminClient";
import { AdminClientContext } from "./context/auth/AdminClient";
import { WhoAmIContextProvider } from "./context/whoami/WhoAmI";
export const mainPageContentId = "kc-main-content-page-container";
@ -37,7 +37,7 @@ const AppContexts: FunctionComponent<AdminClientProps> = ({
adminClient,
}) => (
<Router>
<AdminClient.Provider value={{ keycloak, adminClient }}>
<AdminClientContext.Provider value={{ keycloak, adminClient }}>
<WhoAmIContextProvider>
<RealmsProvider>
<RealmContextProvider>
@ -51,7 +51,7 @@ const AppContexts: FunctionComponent<AdminClientProps> = ({
</RealmContextProvider>
</RealmsProvider>
</WhoAmIContextProvider>
</AdminClient.Provider>
</AdminClientContext.Provider>
</Router>
);

View file

@ -1,9 +1,10 @@
import { createContext, FunctionComponent, useState } from "react";
import { FunctionComponent, useState } from "react";
import { useTranslation } from "react-i18next";
import { AlertVariant } from "@patternfly/react-core";
import axios from "axios";
import type { AxiosError } from "axios";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
import { AlertPanel } from "./AlertPanel";
@ -20,7 +21,10 @@ type AlertProps = {
addError: AddErrorFunction;
};
export const AlertContext = createContext<AlertProps | undefined>(undefined);
export const AlertContext = createNamedContext<AlertProps | undefined>(
"AlertContext",
undefined
);
export const useAlerts = () => useRequiredContext(AlertContext);

View file

@ -9,7 +9,7 @@ import { FunctionComponent } from "react";
import { HashRouter } from "react-router-dom";
import { describe, expect, it } from "vitest";
import { AccessContextProvider } from "../../context/access/Access";
import { AdminClient } from "../../context/auth/AdminClient";
import { AdminClientContext } from "../../context/auth/AdminClient";
import { RealmContext } from "../../context/realm-context/RealmContext";
import { ServerInfoContext } from "../../context/server-info/ServerInfoProvider";
import serverInfo from "../../context/server-info/__tests__/mock.json";
@ -31,13 +31,13 @@ const MockAdminClient: FunctionComponent = ({ children }) => {
<ServerInfoContext.Provider
value={serverInfo as unknown as ServerInfoRepresentation}
>
<AdminClient.Provider value={{ keycloak, adminClient }}>
<AdminClientContext.Provider value={{ keycloak, adminClient }}>
<WhoAmIContextProvider>
<RealmContext.Provider value={{ realm: "master" }}>
<AccessContextProvider>{children}</AccessContextProvider>
</RealmContext.Provider>
</WhoAmIContextProvider>
</AdminClient.Provider>
</AdminClientContext.Provider>
</ServerInfoContext.Provider>
</HashRouter>
);

View file

@ -9,8 +9,10 @@ import {
TextContent,
} from "@patternfly/react-core";
import { ExternalLinkAltIcon, HelpIcon } from "@patternfly/react-icons";
import { createContext, FunctionComponent, useState } from "react";
import { FunctionComponent, useState } from "react";
import { useTranslation } from "react-i18next";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
import helpUrls from "../../help-urls";
@ -21,7 +23,8 @@ type HelpContextProps = {
toggleHelp: () => void;
};
export const HelpContext = createContext<HelpContextProps | undefined>(
export const HelpContext = createNamedContext<HelpContextProps | undefined>(
"HelpContext",
undefined
);

View file

@ -1,15 +1,10 @@
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import { sortBy } from "lodash-es";
import {
createContext,
FunctionComponent,
useCallback,
useMemo,
useState,
} from "react";
import { FunctionComponent, useCallback, useMemo, useState } from "react";
import axios from "axios";
import { RecentUsed } from "../components/realm-selector/recent-used";
import { createNamedContext } from "../utils/createNamedContext";
import useRequiredContext from "../utils/useRequiredContext";
import { useAdminClient, useFetch } from "./auth/AdminClient";
@ -20,7 +15,8 @@ type RealmsContextProps = {
refresh: () => Promise<void>;
};
export const RealmsContext = createContext<RealmsContextProps | undefined>(
export const RealmsContext = createNamedContext<RealmsContextProps | undefined>(
"RealmsContext",
undefined
);

View file

@ -1,7 +1,8 @@
import type { AccessType } from "@keycloak/keycloak-admin-client/lib/defs/whoAmIRepresentation";
import { createContext, FunctionComponent, useEffect, useState } from "react";
import { FunctionComponent, useEffect, useState } from "react";
import { useRealm } from "../../context/realm-context/RealmContext";
import { useWhoAmI } from "../../context/whoami/WhoAmI";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
type AccessContextProps = {
@ -9,7 +10,8 @@ type AccessContextProps = {
hasSomeAccess: (...types: AccessType[]) => boolean;
};
export const AccessContext = createContext<AccessContextProps | undefined>(
export const AccessContext = createNamedContext<AccessContextProps | undefined>(
"AccessContext",
undefined
);

View file

@ -1,10 +1,11 @@
import KeycloakAdminClient from "@keycloak/keycloak-admin-client";
import axios from "axios";
import Keycloak from "keycloak-js";
import { createContext, DependencyList, useEffect } from "react";
import { DependencyList, useEffect } from "react";
import { useErrorHandler } from "react-error-boundary";
import environment from "../../environment";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
export type AdminClientProps = {
@ -12,11 +13,11 @@ export type AdminClientProps = {
adminClient: KeycloakAdminClient;
};
export const AdminClient = createContext<AdminClientProps | undefined>(
undefined
);
export const AdminClientContext = createNamedContext<
AdminClientProps | undefined
>("AdminClientContext", undefined);
export const useAdminClient = () => useRequiredContext(AdminClient);
export const useAdminClient = () => useRequiredContext(AdminClientContext);
/**
* Util function to only set the state when the component is still mounted.

View file

@ -1,4 +1,4 @@
import { createContext, FunctionComponent, useEffect, useMemo } from "react";
import { FunctionComponent, useEffect, useMemo } from "react";
import { useRouteMatch } from "react-router-dom";
import { RecentUsed } from "../../components/realm-selector/recent-used";
import {
@ -6,6 +6,7 @@ import {
DashboardRoute,
} from "../../dashboard/routes/Dashboard";
import environment from "../../environment";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
import { useAdminClient } from "../auth/AdminClient";
@ -13,7 +14,8 @@ type RealmContextType = {
realm: string;
};
export const RealmContext = createContext<RealmContextType | undefined>(
export const RealmContext = createNamedContext<RealmContextType | undefined>(
"RealmContext",
undefined
);

View file

@ -1,13 +1,14 @@
import { createContext, FunctionComponent, useState } from "react";
import { FunctionComponent, useState } from "react";
import type { ServerInfoRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation";
import { sortProviders } from "../../util";
import { useAdminClient, useFetch } from "../auth/AdminClient";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
export const ServerInfoContext = createContext<
export const ServerInfoContext = createNamedContext<
ServerInfoRepresentation | undefined
>(undefined);
>("ServerInfoContext", undefined);
export const useServerInfo = () => useRequiredContext(ServerInfoContext);

View file

@ -1,8 +1,10 @@
import type WhoAmIRepresentation from "@keycloak/keycloak-admin-client/lib/defs/whoAmIRepresentation";
import type { AccessType } from "@keycloak/keycloak-admin-client/lib/defs/whoAmIRepresentation";
import { createContext, FunctionComponent, useState } from "react";
import { FunctionComponent, useState } from "react";
import environment from "../../environment";
import i18n, { DEFAULT_LOCALE } from "../../i18n";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
import { useAdminClient, useFetch } from "../auth/AdminClient";
@ -53,7 +55,10 @@ type WhoAmIProps = {
whoAmI: WhoAmI;
};
export const WhoAmIContext = createContext<WhoAmIProps | undefined>(undefined);
export const WhoAmIContext = createNamedContext<WhoAmIProps | undefined>(
"WhoAmIContext",
undefined
);
export const useWhoAmI = () => useRequiredContext(WhoAmIContext);

View file

@ -1,5 +1,6 @@
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
import { createContext, FunctionComponent, useState } from "react";
import { FunctionComponent, useState } from "react";
import { createNamedContext } from "../utils/createNamedContext";
import useRequiredContext from "../utils/useRequiredContext";
type SubGroupsProps = {
@ -10,7 +11,10 @@ type SubGroupsProps = {
currentGroup: () => GroupRepresentation | undefined;
};
const SubGroupContext = createContext<SubGroupsProps | undefined>(undefined);
const SubGroupsContext = createNamedContext<SubGroupsProps | undefined>(
"SubGroupsContext",
undefined
);
export const SubGroups: FunctionComponent = ({ children }) => {
const [subGroups, setSubGroups] = useState<GroupRepresentation[]>([]);
@ -22,12 +26,12 @@ export const SubGroups: FunctionComponent = ({ children }) => {
);
const currentGroup = () => subGroups[subGroups.length - 1];
return (
<SubGroupContext.Provider
<SubGroupsContext.Provider
value={{ subGroups, setSubGroups, clear, remove, currentGroup }}
>
{children}
</SubGroupContext.Provider>
</SubGroupsContext.Provider>
);
};
export const useSubGroups = () => useRequiredContext(SubGroupContext);
export const useSubGroups = () => useRequiredContext(SubGroupsContext);

View file

@ -1,10 +1,11 @@
import type UserProfileConfig from "@keycloak/keycloak-admin-client/lib/defs/userProfileConfig";
import { AlertVariant } from "@patternfly/react-core";
import { createContext, FunctionComponent, useState } from "react";
import { FunctionComponent, useState } from "react";
import { useTranslation } from "react-i18next";
import { useAlerts } from "../../components/alert/Alerts";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useRealm } from "../../context/realm-context/RealmContext";
import { createNamedContext } from "../../utils/createNamedContext";
import useRequiredContext from "../../utils/useRequiredContext";
type UserProfileProps = {
@ -23,9 +24,9 @@ export type SaveOptions = {
errorMessageKey?: string;
};
export const UserProfile = createContext<UserProfileProps | undefined>(
undefined
);
export const UserProfileContext = createNamedContext<
UserProfileProps | undefined
>("UserProfileContext", undefined);
export const UserProfileProvider: FunctionComponent = ({ children }) => {
const { adminClient } = useAdminClient();
@ -71,10 +72,10 @@ export const UserProfileProvider: FunctionComponent = ({ children }) => {
};
return (
<UserProfile.Provider value={{ config, save, isSaving }}>
<UserProfileContext.Provider value={{ config, save, isSaving }}>
{children}
</UserProfile.Provider>
</UserProfileContext.Provider>
);
};
export const useUserProfile = () => useRequiredContext(UserProfile);
export const useUserProfile = () => useRequiredContext(UserProfileContext);

View file

@ -0,0 +1,11 @@
import type { Context } from "react";
import { createContext } from "react";
export type NamedContext<T> = Context<T> &
Required<Pick<Context<T>, "displayName">>;
export function createNamedContext<T>(displayName: string, defaultValue: T) {
const context = createContext(defaultValue);
context.displayName = displayName;
return context as NamedContext<T>;
}