Add useToggle hook to manage toggleable state (#1600)
This commit is contained in:
parent
31e1415758
commit
61b2689864
33 changed files with 197 additions and 112 deletions
61
package-lock.json
generated
61
package-lock.json
generated
|
@ -38,6 +38,7 @@
|
|||
"@testing-library/cypress": "^8.0.2",
|
||||
"@testing-library/jest-dom": "^5.15.1",
|
||||
"@testing-library/react": "^12.1.1",
|
||||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@types/dagre": "^0.7.45",
|
||||
"@types/file-saver": "^2.0.4",
|
||||
"@types/lodash": "^4.14.177",
|
||||
|
@ -4483,6 +4484,35 @@
|
|||
"react-dom": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@testing-library/react-hooks": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz",
|
||||
"integrity": "sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@types/react": ">=16.9.0",
|
||||
"@types/react-dom": ">=16.9.0",
|
||||
"@types/react-test-renderer": ">=16.9.0",
|
||||
"react-error-boundary": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0",
|
||||
"react-test-renderer": ">=16.9.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"react-test-renderer": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||
|
@ -5002,6 +5032,15 @@
|
|||
"@types/react-router": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-test-renderer": {
|
||||
"version": "17.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz",
|
||||
"integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||
|
@ -24660,6 +24699,19 @@
|
|||
"@testing-library/dom": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"@testing-library/react-hooks": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz",
|
||||
"integrity": "sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@types/react": ">=16.9.0",
|
||||
"@types/react-dom": ">=16.9.0",
|
||||
"@types/react-test-renderer": ">=16.9.0",
|
||||
"react-error-boundary": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||
|
@ -25176,6 +25228,15 @@
|
|||
"@types/react-router": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-test-renderer": {
|
||||
"version": "17.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz",
|
||||
"integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
"@testing-library/cypress": "^8.0.2",
|
||||
"@testing-library/jest-dom": "^5.15.1",
|
||||
"@testing-library/react": "^12.1.1",
|
||||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@types/dagre": "^0.7.45",
|
||||
"@types/file-saver": "^2.0.4",
|
||||
"@types/lodash": "^4.14.177",
|
||||
|
|
|
@ -132,16 +132,12 @@ export const Header = () => {
|
|||
const KebabDropdown = () => {
|
||||
const [isDropdownOpen, setDropdownOpen] = useState(false);
|
||||
|
||||
const onDropdownToggle = () => {
|
||||
setDropdownOpen(!isDropdownOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
id="user-dropdown-kebab"
|
||||
isPlain
|
||||
position="right"
|
||||
toggle={<KebabToggle onToggle={onDropdownToggle} />}
|
||||
toggle={<KebabToggle onToggle={setDropdownOpen} />}
|
||||
isOpen={isDropdownOpen}
|
||||
dropdownItems={kebabDropdownItems}
|
||||
/>
|
||||
|
@ -152,10 +148,6 @@ export const Header = () => {
|
|||
const { whoAmI } = useWhoAmI();
|
||||
const [isDropdownOpen, setDropdownOpen] = useState(false);
|
||||
|
||||
const onDropdownToggle = () => {
|
||||
setDropdownOpen(!isDropdownOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
isPlain
|
||||
|
@ -163,7 +155,7 @@ export const Header = () => {
|
|||
id="user-dropdown"
|
||||
isOpen={isDropdownOpen}
|
||||
toggle={
|
||||
<DropdownToggle onToggle={onDropdownToggle}>
|
||||
<DropdownToggle onToggle={setDropdownOpen}>
|
||||
{whoAmI.getDisplayName()}
|
||||
</DropdownToggle>
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import { useRealm } from "../context/realm-context/RealmContext";
|
|||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { toUpperCase } from "../util";
|
||||
import useToggle from "../utils/useToggle";
|
||||
import { DuplicateFlowModal } from "./DuplicateFlowModal";
|
||||
import { toCreateFlow } from "./routes/CreateFlow";
|
||||
import { toFlow } from "./routes/Flow";
|
||||
|
@ -55,7 +56,7 @@ export default function AuthenticationSection() {
|
|||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const [selectedFlow, setSelectedFlow] = useState<AuthenticationType>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [open, toggleOpen, setOpen] = useToggle();
|
||||
|
||||
const loader = async () => {
|
||||
const clients = await adminClient.clients.find();
|
||||
|
@ -202,7 +203,7 @@ export default function AuthenticationSection() {
|
|||
<DuplicateFlowModal
|
||||
name={selectedFlow ? selectedFlow.alias! : ""}
|
||||
description={selectedFlow?.description!}
|
||||
toggleDialog={() => setOpen(!open)}
|
||||
toggleDialog={toggleOpen}
|
||||
onComplete={() => {
|
||||
refresh();
|
||||
setOpen(false);
|
||||
|
|
|
@ -40,6 +40,7 @@ import { AddSubFlowModal, Flow } from "./components/modals/AddSubFlowModal";
|
|||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { DuplicateFlowModal } from "./DuplicateFlowModal";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import useToggle from "../utils/useToggle";
|
||||
import { toAuthentication } from "./routes/Authentication";
|
||||
import { EditFlowModal } from "./EditFlowModal";
|
||||
|
||||
|
@ -69,7 +70,7 @@ export default function FlowDetails() {
|
|||
const [showAddSubFlowDialog, setShowSubFlowDialog] = useState<boolean>();
|
||||
const [selectedExecution, setSelectedExecution] =
|
||||
useState<ExpandableExecution>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [open, toggleOpen, setOpen] = useToggle();
|
||||
const [edit, setEdit] = useState(false);
|
||||
|
||||
useFetch(
|
||||
|
@ -280,7 +281,7 @@ export default function FlowDetails() {
|
|||
<DuplicateFlowModal
|
||||
name={flow?.alias!}
|
||||
description={flow?.description!}
|
||||
toggleDialog={() => setOpen(!open)}
|
||||
toggleDialog={toggleOpen}
|
||||
onComplete={() => {
|
||||
refresh();
|
||||
setOpen(false);
|
||||
|
|
|
@ -47,7 +47,7 @@ export const EditFlowDropdown = ({
|
|||
data-testid={`${execution.displayName}-edit-dropdown`}
|
||||
isOpen={open}
|
||||
toggle={
|
||||
<DropdownToggle onToggle={(open) => setOpen(open)}>
|
||||
<DropdownToggle onToggle={setOpen}>
|
||||
<PlusIcon />
|
||||
</DropdownToggle>
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export const FlowRequirementDropdown = ({
|
|||
<Select
|
||||
className="keycloak__authentication__requirement-dropdown"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setOpen(!open)}
|
||||
onToggle={setOpen}
|
||||
onSelect={(_event, value) => {
|
||||
flow.requirement = value.toString();
|
||||
onChange(flow);
|
||||
|
|
|
@ -151,7 +151,7 @@ export const AddSubFlowModal = ({
|
|||
<Select
|
||||
menuAppendTo="parent"
|
||||
toggleId="flowType"
|
||||
onToggle={() => setOpen(!open)}
|
||||
onToggle={setOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setOpen(false);
|
||||
|
@ -194,9 +194,9 @@ export const AddSubFlowModal = ({
|
|||
<Select
|
||||
menuAppendTo="parent"
|
||||
toggleId="provider"
|
||||
onToggle={(toggle) => setOpenProvider(toggle)}
|
||||
onToggle={setOpenProvider}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
onChange(value.toString());
|
||||
setOpenProvider(false);
|
||||
}}
|
||||
selections={value.displayName}
|
||||
|
|
|
@ -37,9 +37,9 @@ export const FlowType = () => {
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="flowType"
|
||||
onToggle={() => setOpen(!open)}
|
||||
onToggle={setOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
onChange(value.toString());
|
||||
setOpen(false);
|
||||
}}
|
||||
selections={t(`top-level-flow-type.${value}`)}
|
||||
|
|
|
@ -37,7 +37,7 @@ export const ChangeTypeDropdown = ({
|
|||
selections={[]}
|
||||
isDisabled={selectedRows.length === 0}
|
||||
placeholderText={t("changeTypeTo")}
|
||||
onToggle={(isExpanded) => setOpen(isExpanded)}
|
||||
onToggle={setOpen}
|
||||
onSelect={async (_, value) => {
|
||||
try {
|
||||
await Promise.all(
|
||||
|
|
|
@ -221,9 +221,7 @@ export default function ClientScopesSection() {
|
|||
</ToolbarItem>
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
toggle={
|
||||
<KebabToggle onToggle={() => setKebabOpen(!kebabOpen)} />
|
||||
}
|
||||
toggle={<KebabToggle onToggle={setKebabOpen} />}
|
||||
isOpen={kebabOpen}
|
||||
isPlain
|
||||
dropdownItems={[
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { Button } from "@patternfly/react-core";
|
||||
|
||||
|
@ -9,6 +9,7 @@ import type { ServerInfoRepresentation } from "@keycloak/keycloak-admin-client/l
|
|||
import type WhoAmIRepresentation from "@keycloak/keycloak-admin-client/lib/defs/whoAmIRepresentation";
|
||||
import { ServerInfoContext } from "../../context/server-info/ServerInfoProvider";
|
||||
import serverInfo from "../../context/server-info/__tests__/mock.json";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import { AddMapperDialog, AddMapperDialogModalProps } from "./MapperDialog";
|
||||
import { WhoAmI, WhoAmIContext } from "../../context/whoami/WhoAmI";
|
||||
|
||||
|
@ -16,7 +17,7 @@ import whoami from "../../context/whoami/__tests__/mock-whoami.json";
|
|||
|
||||
describe("MapperDialog", () => {
|
||||
const Test = (args: AddMapperDialogModalProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [open, toggleOpen, setOpen] = useToggle();
|
||||
|
||||
return (
|
||||
<ServerInfoContext.Provider
|
||||
|
@ -28,11 +29,7 @@ describe("MapperDialog", () => {
|
|||
whoAmI: new WhoAmI(whoami as WhoAmIRepresentation),
|
||||
}}
|
||||
>
|
||||
<AddMapperDialog
|
||||
{...args}
|
||||
open={open}
|
||||
toggleDialog={() => setOpen(!open)}
|
||||
/>
|
||||
<AddMapperDialog {...args} open={open} toggleDialog={toggleOpen} />
|
||||
<Button onClick={() => setOpen(true)}>
|
||||
{!open ? "Show" : "Hide"}
|
||||
</Button>
|
||||
|
|
|
@ -142,7 +142,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
variant={SelectVariant.single}
|
||||
isOpen={openType}
|
||||
selections={value}
|
||||
onToggle={() => setOpenType(!openType)}
|
||||
onToggle={setOpenType}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
setOpenType(false);
|
||||
|
@ -173,7 +173,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
<Select
|
||||
toggleId="kc-protocol"
|
||||
required
|
||||
onToggle={() => isOpen(!open)}
|
||||
onToggle={isOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
isOpen(false);
|
||||
|
|
|
@ -72,10 +72,7 @@ export const SearchDropdown = ({
|
|||
<Dropdown
|
||||
className="keycloak__client-scopes__searchtype"
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
id="toggle-id"
|
||||
onToggle={(open) => setSearchToggle(open)}
|
||||
>
|
||||
<DropdownToggle id="toggle-id" onToggle={setSearchToggle}>
|
||||
<FilterIcon /> {t(`clientScopeSearch.${searchType}`)}
|
||||
</DropdownToggle>
|
||||
}
|
||||
|
@ -110,7 +107,7 @@ export const SearchToolbar = ({
|
|||
<ToolbarItem>
|
||||
<Select
|
||||
className="keycloak__client-scopes__searchtype"
|
||||
onToggle={(open) => setOpen(open)}
|
||||
onToggle={setOpen}
|
||||
isOpen={open}
|
||||
selections={[
|
||||
type === AllClientScopes.none
|
||||
|
@ -142,7 +139,7 @@ export const SearchToolbar = ({
|
|||
<ToolbarItem>
|
||||
<Select
|
||||
className="keycloak__client-scopes__searchtype"
|
||||
onToggle={(open) => setOpen(open)}
|
||||
onToggle={setOpen}
|
||||
isOpen={open}
|
||||
selections={[t(`protocolTypes.${protocol}`)]}
|
||||
onSelect={(_, value) => {
|
||||
|
|
|
@ -33,6 +33,7 @@ import {
|
|||
ClientScopeDefaultOptionalType,
|
||||
} from "../../components/client-scope/ClientScopeTypes";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import { toMapper } from "../routes/Mapper";
|
||||
import { toClientScope } from "../routes/ClientScope";
|
||||
|
||||
|
@ -42,7 +43,7 @@ export default function ClientScopeForm() {
|
|||
useState<ClientScopeDefaultOptionalType>();
|
||||
const history = useHistory();
|
||||
const { realm } = useRealm();
|
||||
const [hide, setHide] = useState(false);
|
||||
const [hide, toggleHide] = useToggle();
|
||||
|
||||
const adminClient = useAdminClient();
|
||||
const { id, type } = useParams<{ id: string; type: AllClientScopes }>();
|
||||
|
@ -249,7 +250,7 @@ export default function ClientScopeForm() {
|
|||
dropdownItems={
|
||||
clientScope
|
||||
? [
|
||||
<DropdownItem key="delete" onClick={() => toggleDeleteDialog()}>
|
||||
<DropdownItem key="delete" onClick={toggleDeleteDialog}>
|
||||
{t("common:delete")}
|
||||
</DropdownItem>,
|
||||
]
|
||||
|
@ -299,7 +300,7 @@ export default function ClientScopeForm() {
|
|||
type={"client-scope"}
|
||||
loader={loader}
|
||||
save={assignRoles}
|
||||
onHideRolesToggle={() => setHide(!hide)}
|
||||
onHideRolesToggle={toggleHide}
|
||||
/>
|
||||
</Tab>
|
||||
</KeycloakTabs>
|
||||
|
|
|
@ -300,7 +300,7 @@ export const AdvancedTab = ({
|
|||
/>
|
||||
<ExpandableSection
|
||||
toggleText={t("registeredClusterNodes")}
|
||||
onToggle={() => setExpanded(!expanded)}
|
||||
onToggle={setExpanded}
|
||||
isExpanded={expanded}
|
||||
>
|
||||
<KeycloakDataTable
|
||||
|
|
|
@ -43,6 +43,7 @@ import {
|
|||
convertToFormValues,
|
||||
exportClient,
|
||||
} from "../util";
|
||||
import useToggle from "../utils/useToggle";
|
||||
import { AdvancedTab } from "./AdvancedTab";
|
||||
import { ClientSettings } from "./ClientSettings";
|
||||
import { Credentials } from "./credentials/Credentials";
|
||||
|
@ -115,7 +116,7 @@ const ClientDetailHeader = ({
|
|||
}, [client, t]);
|
||||
|
||||
const dropdownItems = [
|
||||
<DropdownItem key="download" onClick={() => toggleDownloadDialog()}>
|
||||
<DropdownItem key="download" onClick={toggleDownloadDialog}>
|
||||
{t("downloadAdapterConfig")}
|
||||
</DropdownItem>,
|
||||
<DropdownItem key="export" onClick={() => exportClient(client)}>
|
||||
|
@ -127,7 +128,7 @@ const ClientDetailHeader = ({
|
|||
<DropdownItem
|
||||
data-testid="delete-client"
|
||||
key="delete"
|
||||
onClick={() => toggleDeleteDialog()}
|
||||
onClick={toggleDeleteDialog}
|
||||
>
|
||||
{t("common:delete")}
|
||||
</DropdownItem>,
|
||||
|
@ -180,11 +181,8 @@ export default function ClientDetails() {
|
|||
|
||||
const history = useHistory();
|
||||
|
||||
const [downloadDialogOpen, setDownloadDialogOpen] = useState(false);
|
||||
const toggleDownloadDialog = () => setDownloadDialogOpen(!downloadDialogOpen);
|
||||
const [changeAuthenticatorOpen, setChangeAuthenticatorOpen] = useState(false);
|
||||
const toggleChangeAuthenticator = () =>
|
||||
setChangeAuthenticatorOpen(!changeAuthenticatorOpen);
|
||||
const [downloadDialogOpen, toggleDownloadDialogOpen] = useToggle();
|
||||
const [changeAuthenticatorOpen, toggleChangeAuthenticatorOpen] = useToggle();
|
||||
const [clientScopeSubTab, setClientScopeSubTab] = useState(30);
|
||||
const [authorizationSubTab, setAuthorizationSubTab] = useState(40);
|
||||
|
||||
|
@ -259,7 +257,7 @@ export default function ClientDetails() {
|
|||
client?.clientAuthenticatorType !== clientAuthenticatorType &&
|
||||
!confirmed
|
||||
) {
|
||||
toggleChangeAuthenticator();
|
||||
toggleChangeAuthenticatorOpen();
|
||||
return;
|
||||
}
|
||||
const redirectUris = toValue(form.getValues()["redirectUris"]);
|
||||
|
@ -343,7 +341,7 @@ export default function ClientDetails() {
|
|||
clientAuthenticatorType: clientAuthenticatorType,
|
||||
})}
|
||||
open={changeAuthenticatorOpen}
|
||||
toggleDialog={toggleChangeAuthenticator}
|
||||
toggleDialog={toggleChangeAuthenticatorOpen}
|
||||
onConfirm={() => save({ confirmed: true })}
|
||||
>
|
||||
<>
|
||||
|
@ -360,7 +358,7 @@ export default function ClientDetails() {
|
|||
id={client.id!}
|
||||
protocol={client.protocol}
|
||||
open={downloadDialogOpen}
|
||||
toggleDialog={toggleDownloadDialog}
|
||||
toggleDialog={toggleDownloadDialogOpen}
|
||||
/>
|
||||
<Controller
|
||||
name="enabled"
|
||||
|
@ -373,7 +371,7 @@ export default function ClientDetails() {
|
|||
client={client}
|
||||
save={save}
|
||||
toggleDeleteDialog={toggleDeleteDialog}
|
||||
toggleDownloadDialog={toggleDownloadDialog}
|
||||
toggleDownloadDialog={toggleDownloadDialogOpen}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -182,9 +182,9 @@ export const ClientSettings = ({
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="loginTheme"
|
||||
onToggle={() => setLoginThemeOpen(!loginThemeOpen)}
|
||||
onToggle={setLoginThemeOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
onChange(value.toString());
|
||||
setLoginThemeOpen(false);
|
||||
}}
|
||||
selections={value || t("common:choose")}
|
||||
|
|
|
@ -42,9 +42,9 @@ export const GeneralSettings = () => {
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
id="kc-type"
|
||||
onToggle={() => isOpen(!open)}
|
||||
onToggle={isOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
onChange(value.toString());
|
||||
isOpen(false);
|
||||
}}
|
||||
selections={value}
|
||||
|
|
|
@ -78,7 +78,7 @@ export const SamlConfig = () => {
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="samlNameIdFormat"
|
||||
onToggle={(open) => setNameFormatOpen(open)}
|
||||
onToggle={setNameFormatOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value.toString());
|
||||
setNameFormatOpen(false);
|
||||
|
|
|
@ -85,7 +85,7 @@ export const SamlSignature = () => {
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="signatureAlgorithm"
|
||||
onToggle={(open) => setAlgOpen(open)}
|
||||
onToggle={setAlgOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value.toString());
|
||||
setAlgOpen(false);
|
||||
|
@ -126,7 +126,7 @@ export const SamlSignature = () => {
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="signatureKeyName"
|
||||
onToggle={(open) => setKeyOpen(open)}
|
||||
onToggle={setKeyOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value.toString());
|
||||
setKeyOpen(false);
|
||||
|
@ -167,7 +167,7 @@ export const SamlSignature = () => {
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="canonicalization"
|
||||
onToggle={(open) => setCanOpen(open)}
|
||||
onToggle={setCanOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value.toString());
|
||||
setCanOpen(false);
|
||||
|
|
|
@ -118,7 +118,7 @@ export const AdvancedSettings = ({
|
|||
<Select
|
||||
toggleId="keyForCodeExchange"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setOpen(!open)}
|
||||
onToggle={setOpen}
|
||||
isOpen={open}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
|
|
@ -76,7 +76,7 @@ export const AuthenticationOverrides = ({
|
|||
<Select
|
||||
toggleId="browserFlow"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setBrowserFlowOpen(!browserFlowOpen)}
|
||||
onToggle={setBrowserFlowOpen}
|
||||
isOpen={browserFlowOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
@ -109,7 +109,7 @@ export const AuthenticationOverrides = ({
|
|||
<Select
|
||||
toggleId="directGrant"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setDirectGrantOpen(!directGrantOpen)}
|
||||
onToggle={setDirectGrantOpen}
|
||||
isOpen={directGrantOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
|
|
@ -125,7 +125,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<Select
|
||||
toggleId="accessTokenSignatureAlgorithm"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setAccessTokenOpen(!accessTokenOpen)}
|
||||
onToggle={setAccessTokenOpen}
|
||||
isOpen={accessTokenOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
@ -157,7 +157,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<Select
|
||||
toggleId="idTokenSignatureAlgorithm"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setIdTokenOpen(!idTokenOpen)}
|
||||
onToggle={setIdTokenOpen}
|
||||
isOpen={idTokenOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
@ -189,9 +189,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<Select
|
||||
toggleId="idTokenEncryptionKeyManagementAlgorithm"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() =>
|
||||
setIdTokenKeyManagementOpen(!idTokenKeyManagementOpen)
|
||||
}
|
||||
onToggle={setIdTokenKeyManagementOpen}
|
||||
isOpen={idTokenKeyManagementOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
@ -223,7 +221,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<Select
|
||||
toggleId="idTokenEncryptionContentEncryptionAlgorithm"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() => setIdTokenContentOpen(!idTokenContentOpen)}
|
||||
onToggle={setIdTokenContentOpen}
|
||||
isOpen={idTokenContentOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
@ -255,9 +253,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<Select
|
||||
toggleId="userInfoSignedResponseAlgorithm"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() =>
|
||||
setUserInfoSignedResponseOpen(!userInfoSignedResponseOpen)
|
||||
}
|
||||
onToggle={setUserInfoSignedResponseOpen}
|
||||
isOpen={userInfoSignedResponseOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
@ -289,9 +285,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<Select
|
||||
toggleId="requestObjectSignatureAlgorithm"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() =>
|
||||
setRequestObjectSignatureOpen(!requestObjectSignatureOpen)
|
||||
}
|
||||
onToggle={setRequestObjectSignatureOpen}
|
||||
isOpen={requestObjectSignatureOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
@ -323,9 +317,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
<Select
|
||||
toggleId="requestObjectRequired"
|
||||
variant={SelectVariant.single}
|
||||
onToggle={() =>
|
||||
setRequestObjectRequiredOpen(!requestObjectRequiredOpen)
|
||||
}
|
||||
onToggle={setRequestObjectRequiredOpen}
|
||||
isOpen={requestObjectRequiredOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
|
|
@ -67,7 +67,7 @@ export const TokenLifespan = ({
|
|||
<SplitItem>
|
||||
<Select
|
||||
variant={SelectVariant.single}
|
||||
onToggle={(isExpanded) => setOpen(isExpanded)}
|
||||
onToggle={setOpen}
|
||||
isOpen={open}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value);
|
||||
|
|
|
@ -155,7 +155,7 @@ export const Credentials = ({ clientId, save }: CredentialsProps) => {
|
|||
<Select
|
||||
toggleId="kc-client-authenticator-type"
|
||||
required
|
||||
onToggle={() => isOpen(!open)}
|
||||
onToggle={isOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
isOpen(false);
|
||||
|
|
|
@ -40,9 +40,9 @@ export const SignedJWT = () => {
|
|||
<Select
|
||||
maxHeight={200}
|
||||
toggleId="kc-signature-algorithm"
|
||||
onToggle={() => isOpen(!open)}
|
||||
onToggle={isOpen}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
onChange(value.toString());
|
||||
isOpen(false);
|
||||
}}
|
||||
selections={value || t("anyAlgorithm")}
|
||||
|
|
|
@ -61,7 +61,7 @@ export const KeyForm = ({
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="archiveFormat"
|
||||
onToggle={(isExpanded) => setOpenArchiveFormat(isExpanded)}
|
||||
onToggle={setOpenArchiveFormat}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value.toString());
|
||||
setOpenArchiveFormat(false);
|
||||
|
|
|
@ -105,7 +105,7 @@ export const ImportKeyDialog = ({
|
|||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
toggleId="archiveFormat"
|
||||
onToggle={() => setOpenArchiveFormat(!openArchiveFormat)}
|
||||
onToggle={setOpenArchiveFormat}
|
||||
onSelect={(_, value) => {
|
||||
onChange(value as string);
|
||||
setOpenArchiveFormat(false);
|
||||
|
|
|
@ -26,6 +26,7 @@ import type { ClientForm } from "../ClientDetails";
|
|||
import { GenerateKeyDialog } from "./GenerateKeyDialog";
|
||||
import { useFetch, useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import { ImportKeyDialog, ImportFile } from "./ImportKeyDialog";
|
||||
import { Certificate } from "./Certificate";
|
||||
|
||||
|
@ -47,8 +48,9 @@ export const Keys = ({ clientId, save }: KeysProps) => {
|
|||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const [keyInfo, setKeyInfo] = useState<CertificateRepresentation>();
|
||||
const [openGenerateKeys, setOpenGenerateKeys] = useState(false);
|
||||
const [openImportKeys, setOpenImportKeys] = useState(false);
|
||||
const [openGenerateKeys, toggleOpenGenerateKeys, setOpenGenerateKeys] =
|
||||
useToggle();
|
||||
const [openImportKeys, toggleOpenImportKeys, setOpenImportKeys] = useToggle();
|
||||
|
||||
const useJwksUrl = useWatch({
|
||||
control,
|
||||
|
@ -104,15 +106,12 @@ export const Keys = ({ clientId, save }: KeysProps) => {
|
|||
<PageSection variant="light" className="keycloak__form">
|
||||
{openGenerateKeys && (
|
||||
<GenerateKeyDialog
|
||||
toggleDialog={() => setOpenGenerateKeys(!openGenerateKeys)}
|
||||
toggleDialog={toggleOpenGenerateKeys}
|
||||
save={generate}
|
||||
/>
|
||||
)}
|
||||
{openImportKeys && (
|
||||
<ImportKeyDialog
|
||||
toggleDialog={() => setOpenImportKeys(!openImportKeys)}
|
||||
save={importKey}
|
||||
/>
|
||||
<ImportKeyDialog toggleDialog={toggleOpenImportKeys} save={importKey} />
|
||||
)}
|
||||
<Card isFlat>
|
||||
<CardHeader>
|
||||
|
|
|
@ -26,9 +26,10 @@ import {
|
|||
clientScopeTypesDropdown,
|
||||
} from "../../components/client-scope/ClientScopeTypes";
|
||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
import { getProtocolName } from "../utils";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
|
||||
import "./client-scopes.css";
|
||||
import { getProtocolName } from "../utils";
|
||||
|
||||
export type AddScopeDialogProps = {
|
||||
clientScopes: ClientScopeRepresentation[];
|
||||
|
@ -68,11 +69,11 @@ export const AddScopeDialog = ({
|
|||
const [key, setKey] = useState(0);
|
||||
const refresh = () => setKey(key + 1);
|
||||
|
||||
const [isFilterTypeDropdownOpen, setIsFilterTypeDropdownOpen] =
|
||||
useState(false);
|
||||
const [isFilterTypeDropdownOpen, toggleIsFilterTypeDropdownOpen] =
|
||||
useToggle();
|
||||
|
||||
const [isProtocolTypeDropdownOpen, setIsProtocolTypeDropdownOpen] =
|
||||
useState(false);
|
||||
const [isProtocolTypeDropdownOpen, toggleIsProtocolTypeDropdownOpen] =
|
||||
useToggle(false);
|
||||
|
||||
useEffect(() => {
|
||||
refresh();
|
||||
|
@ -97,14 +98,6 @@ export const AddScopeDialog = ({
|
|||
toggleDialog();
|
||||
};
|
||||
|
||||
const onFilterTypeDropdownToggle = () => {
|
||||
setIsFilterTypeDropdownOpen(!isFilterTypeDropdownOpen);
|
||||
};
|
||||
|
||||
const onProtocolTypeDropdownToggle = () => {
|
||||
setIsProtocolTypeDropdownOpen(!isProtocolTypeDropdownOpen);
|
||||
};
|
||||
|
||||
const onFilterTypeDropdownSelect = (filterType: string) => {
|
||||
if (filterType === FilterType.Name) {
|
||||
setFilterType(FilterType.Protocol);
|
||||
|
@ -112,7 +105,7 @@ export const AddScopeDialog = ({
|
|||
setFilterType(FilterType.Name);
|
||||
}
|
||||
|
||||
setIsFilterTypeDropdownOpen(!isFilterTypeDropdownOpen);
|
||||
toggleIsFilterTypeDropdownOpen();
|
||||
};
|
||||
|
||||
const onProtocolTypeDropdownSelect = (protocolType: string) => {
|
||||
|
@ -124,7 +117,7 @@ export const AddScopeDialog = ({
|
|||
setProtocolType(ProtocolType.All);
|
||||
}
|
||||
|
||||
setIsProtocolTypeDropdownOpen(!isProtocolTypeDropdownOpen);
|
||||
toggleIsProtocolTypeDropdownOpen();
|
||||
};
|
||||
|
||||
const protocolTypeOptions = [
|
||||
|
@ -226,7 +219,7 @@ export const AddScopeDialog = ({
|
|||
toggle={
|
||||
<DropdownToggle
|
||||
id="toggle-id-9"
|
||||
onToggle={onFilterTypeDropdownToggle}
|
||||
onToggle={toggleIsFilterTypeDropdownOpen}
|
||||
toggleIndicator={CaretDownIcon}
|
||||
icon={<FilterIcon />}
|
||||
>
|
||||
|
@ -258,7 +251,7 @@ export const AddScopeDialog = ({
|
|||
toggle={
|
||||
<DropdownToggle
|
||||
id="toggle-id-9"
|
||||
onToggle={onFilterTypeDropdownToggle}
|
||||
onToggle={toggleIsFilterTypeDropdownOpen}
|
||||
toggleIndicator={CaretDownIcon}
|
||||
icon={<FilterIcon />}
|
||||
>
|
||||
|
@ -279,7 +272,7 @@ export const AddScopeDialog = ({
|
|||
variant={SelectVariant.single}
|
||||
className="kc-protocolType-select"
|
||||
aria-label="Select Input"
|
||||
onToggle={onProtocolTypeDropdownToggle}
|
||||
onToggle={toggleIsProtocolTypeDropdownOpen}
|
||||
onSelect={(_, value) =>
|
||||
onProtocolTypeDropdownSelect(value.toString())
|
||||
}
|
||||
|
|
41
src/utils/useToggle.test.ts
Normal file
41
src/utils/useToggle.test.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { act, renderHook } from "@testing-library/react-hooks";
|
||||
import useToggle from "./useToggle";
|
||||
|
||||
describe("useToggle", () => {
|
||||
it("has a default value of false", () => {
|
||||
const { result } = renderHook(() => useToggle());
|
||||
const [value] = result.current;
|
||||
|
||||
expect(value).toBe(false);
|
||||
});
|
||||
|
||||
it("uses the initial value", () => {
|
||||
const { result } = renderHook(() => useToggle(true));
|
||||
const [value] = result.current;
|
||||
|
||||
expect(value).toBe(true);
|
||||
});
|
||||
|
||||
it("toggles the value", () => {
|
||||
const { result } = renderHook(() => useToggle());
|
||||
const [, toggleValue] = result.current;
|
||||
|
||||
act(() => toggleValue());
|
||||
|
||||
const [value] = result.current;
|
||||
expect(value).toBe(true);
|
||||
});
|
||||
|
||||
it("sets the value", () => {
|
||||
const { result } = renderHook(() => useToggle());
|
||||
const [, , setValue] = result.current;
|
||||
|
||||
act(() => setValue(true));
|
||||
|
||||
const [value] = result.current;
|
||||
expect(value).toBe(true);
|
||||
});
|
||||
});
|
13
src/utils/useToggle.ts
Normal file
13
src/utils/useToggle.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { useCallback, useState } from "react";
|
||||
|
||||
/**
|
||||
* A hook that allows you toggle a boolean value, useful for toggle buttons, showing and hiding modals, etc.
|
||||
*
|
||||
* @param initialValue The initial value to use, false by default.
|
||||
*/
|
||||
export default function useToggle(initialValue = false) {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
const toggleValue = useCallback(() => setValue((val) => !val), []);
|
||||
|
||||
return [value, toggleValue, setValue] as const;
|
||||
}
|
Loading…
Reference in a new issue