move keycloak select to ui-shared and fix typeahead (#30209)
* move keycloak select to ui-shared and fix typeahead Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Fix the account console test Signed-off-by: Hynek Mlnarik <hmlnarik@redhat.com> * Fix cypress tests Signed-off-by: Hynek Mlnarik <hmlnarik@redhat.com> * fix for when value is an array Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * fix for when value is an array Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * add support for array selecting single value Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * fixed saying open once clicked outside and value Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * small issue when pressing enter Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> --------- Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> Signed-off-by: Hynek Mlnarik <hmlnarik@redhat.com> Co-authored-by: Hynek Mlnarik <hmlnarik@redhat.com>
This commit is contained in:
parent
28fd38d13d
commit
d2e8092c7f
48 changed files with 258 additions and 251 deletions
|
@ -63,10 +63,10 @@ test.describe("Personal info with userprofile enabled", () => {
|
|||
test("render long select options as typeahead", async ({ page }) => {
|
||||
await login(page, user, "jdoe", realm);
|
||||
|
||||
await page.getByText("Alternate Language").click();
|
||||
await page.locator("#alternatelang").click();
|
||||
await page.waitForSelector("text=Italiano");
|
||||
|
||||
await page.getByText("Alternate Language").click();
|
||||
await page.locator("#alternatelang").click();
|
||||
await page.locator("*:focus").press("Control+A");
|
||||
await page.locator("*:focus").pressSequentially("S");
|
||||
await expect(page.getByText("Italiano")).toHaveCount(0);
|
||||
|
|
|
@ -9,8 +9,8 @@ export default defineConfig({
|
|||
video: isCI,
|
||||
projectId: "j4yhox",
|
||||
chromeWebSecurity: false,
|
||||
viewportWidth: 1360,
|
||||
viewportHeight: 768,
|
||||
viewportWidth: 1920,
|
||||
viewportHeight: 1200,
|
||||
defaultCommandTimeout: 30000,
|
||||
numTestsKeptInMemory: 30,
|
||||
experimentalMemoryManagement: true,
|
||||
|
|
|
@ -371,7 +371,7 @@ describe("User profile tabs", () => {
|
|||
createUserPage
|
||||
.goToCreateUser()
|
||||
.assertAttributeLabel(attrName, attrName)
|
||||
.assertAttributeSelect(attrName, supportedOptions, "Choose...")
|
||||
.assertAttributeSelect(attrName, supportedOptions, "Select an option")
|
||||
.setUsername(userName)
|
||||
.setAttributeValueOnSelect(attrName, opt1)
|
||||
.create()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation";
|
||||
import { KeycloakSelect, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import { Button, SelectOption, TextInput } from "@patternfly/react-core";
|
||||
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
|
||||
import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
|
||||
|
@ -6,14 +7,9 @@ import { camelCase } from "lodash-es";
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Controller, useFieldArray, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { defaultContextAttributes } from "../utils";
|
||||
|
||||
import "./key-based-attribute-input.css";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
export type AttributeType = {
|
||||
key?: string;
|
||||
|
|
|
@ -3,6 +3,7 @@ import { DecisionStrategy } from "@keycloak/keycloak-admin-client/lib/defs/polic
|
|||
import {
|
||||
FormErrorText,
|
||||
HelpItem,
|
||||
SelectVariant,
|
||||
TextAreaControl,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
|
@ -39,7 +40,6 @@ import {
|
|||
} from "../routes/PermissionDetails";
|
||||
import { ResourcesPolicySelect } from "./ResourcesPolicySelect";
|
||||
import { ScopeSelect } from "./ScopeSelect";
|
||||
import { SelectVariant } from "../../components/select/KeycloakSelect";
|
||||
|
||||
type FormFields = PolicyRepresentation & {
|
||||
resourceType: string;
|
||||
|
|
|
@ -26,7 +26,7 @@ import {
|
|||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
Variant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { useFetch } from "../../utils/useFetch";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation";
|
||||
import { HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
import { useFetch } from "../../utils/useFetch";
|
||||
|
||||
type Scope = {
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation";
|
||||
import { KeycloakSelect, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import { SelectOption } from "@patternfly/react-core";
|
||||
import { useRef, useState } from "react";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
import { useFetch } from "../../utils/useFetch";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
import { SelectOption } from "@patternfly/react-core";
|
||||
|
||||
type ScopeSelectProps = {
|
||||
clientId: string;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation";
|
||||
import { KeycloakSelect } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
Button,
|
||||
ButtonVariant,
|
||||
|
@ -17,7 +18,6 @@ import {
|
|||
} from "@patternfly/react-icons";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
ClientScopeType,
|
||||
clientScopeTypesDropdown,
|
||||
|
@ -26,7 +26,6 @@ import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState
|
|||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import { getProtocolName } from "../utils";
|
||||
import { KeycloakSelect } from "../../components/select/KeycloakSelect";
|
||||
|
||||
import "./client-scopes.css";
|
||||
|
||||
|
|
|
@ -2,6 +2,12 @@ import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/
|
|||
import type ProtocolMapperRepresentation from "@keycloak/keycloak-admin-client/lib/defs/protocolMapperRepresentation";
|
||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||
import type { ProtocolMapperTypeRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
useHelp,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ClipboardCopy,
|
||||
Form,
|
||||
|
@ -23,7 +29,6 @@ import { QuestionCircleIcon } from "@patternfly/react-icons";
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HelpItem, useHelp } from "@keycloak/keycloak-ui-shared";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
import { UserSelect } from "../../components/users/UserSelect";
|
||||
|
@ -35,10 +40,6 @@ import { useFetch } from "../../utils/useFetch";
|
|||
import { GeneratedCodeTab } from "./GeneratedCodeTab";
|
||||
|
||||
import "./evaluate.css";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
export type EvaluateScopesProps = {
|
||||
clientId: string;
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import { HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { KeycloakSelect, SelectVariant } from "../select/KeycloakSelect";
|
||||
|
||||
export const ListComponent = ({
|
||||
name,
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { KeycloakSelect, SelectVariant } from "../select/KeycloakSelect";
|
||||
import { convertToName } from "./DynamicComponents";
|
||||
import type { ComponentProps } from "./components";
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { KeycloakSelect } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
Grid,
|
||||
GridItem,
|
||||
|
@ -9,7 +10,6 @@ import { UseControllerProps, useController } from "react-hook-form";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import { DefaultValue } from "./KeyValueInput";
|
||||
import { KeycloakSelect } from "../select/KeycloakSelect";
|
||||
|
||||
type KeySelectProp = UseControllerProps & {
|
||||
selectItems: DefaultValue[];
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { KeycloakSelect } from "@keycloak/keycloak-ui-shared";
|
||||
import { SelectOption, TextInput } from "@patternfly/react-core";
|
||||
import { useMemo, useState } from "react";
|
||||
import { UseControllerProps, useController } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { KeycloakSelect } from "../select/KeycloakSelect";
|
||||
import { DefaultValue } from "./KeyValueInput";
|
||||
|
||||
type ValueSelectProps = UseControllerProps & {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
KeycloakSelectProps,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
SelectOption,
|
||||
Split,
|
||||
|
@ -7,11 +10,8 @@ import {
|
|||
TextInput,
|
||||
TextInputProps,
|
||||
} from "@patternfly/react-core";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
KeycloakSelectProps,
|
||||
SelectVariant,
|
||||
} from "../select/KeycloakSelect";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export type Unit = "second" | "minute" | "hour" | "day";
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import type { UserProfileConfig } from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
label,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
Alert,
|
||||
|
@ -18,11 +23,8 @@ import { ReactNode, useState } from "react";
|
|||
import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form } from "react-router-dom";
|
||||
import { SelectVariant, label } from "@keycloak/keycloak-ui-shared";
|
||||
|
||||
import { useAlerts } from "../alert/Alerts";
|
||||
import { UserAttribute } from "./UserDataTable";
|
||||
import { KeycloakSelect } from "../select/KeycloakSelect";
|
||||
|
||||
type UserDataTableAttributeSearchFormProps = {
|
||||
activeFilters: UserAttribute[];
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import type AdminEventRepresentation from "@keycloak/keycloak-admin-client/lib/defs/adminEventRepresentation";
|
||||
import { TextControl } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { CodeEditor, Language } from "@patternfly/react-code-editor";
|
||||
import {
|
||||
ActionGroup,
|
||||
|
@ -32,10 +36,6 @@ import { useTranslation } from "react-i18next";
|
|||
import { useAdminClient } from "../admin-client";
|
||||
import DropdownPanel from "../components/dropdown-panel/DropdownPanel";
|
||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../components/select/KeycloakSelect";
|
||||
import {
|
||||
Action,
|
||||
KeycloakDataTable,
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import type EventRepresentation from "@keycloak/keycloak-admin-client/lib/defs/eventRepresentation";
|
||||
import type EventType from "@keycloak/keycloak-admin-client/lib/defs/eventTypes";
|
||||
import type { RealmEventsConfigRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/realmEventsConfigRepresentation";
|
||||
import { TextControl } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -37,10 +41,6 @@ import {
|
|||
RoutableTabs,
|
||||
useRoutableTab,
|
||||
} from "../components/routable-tabs/RoutableTabs";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../components/select/KeycloakSelect";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
|
|
@ -2,17 +2,15 @@ import type IdentityProviderMapperRepresentation from "@keycloak/keycloak-admin-
|
|||
import type { IdentityProviderMapperTypeRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/identityProviderMapperTypeRepresentation";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectControl,
|
||||
SelectVariant,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, UseFormReturn } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
import type { IdPMapperRepresentationWithAttributes } from "./AddMapper";
|
||||
|
||||
type AddMapperFormProps = {
|
||||
|
|
|
@ -3,7 +3,9 @@ import type IdentityProviderRepresentation from "@keycloak/keycloak-admin-client
|
|||
import {
|
||||
FormErrorText,
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectControl,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
FormGroup,
|
||||
|
@ -16,10 +18,6 @@ import { useState } from "react";
|
|||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
import { useFetch } from "../../utils/useFetch";
|
||||
import useIsFeatureEnabled, { Feature } from "../../utils/useIsFeatureEnabled";
|
||||
import type { FieldProps } from "../component/FormGroupField";
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ExpandableSection,
|
||||
Form,
|
||||
|
@ -8,9 +13,6 @@ import {
|
|||
import { useState } from "react";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { HelpItem, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import { KeycloakSelect } from "../../components/select/KeycloakSelect";
|
||||
import { FormGroupField } from "../component/FormGroupField";
|
||||
import { SwitchField } from "../component/SwitchField";
|
||||
import { TextField } from "../component/TextField";
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { sortProviders } from "../../util";
|
||||
import { ClientIdSecret } from "../component/ClientIdSecret";
|
||||
import { SwitchField } from "../component/SwitchField";
|
||||
import { sortProviders } from "../../util";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { TextField } from "../component/TextField";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
const clientAuthentications = [
|
||||
"client_secret_post",
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { HelpItem, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
|
||||
import { KeycloakSelect } from "../../components/select/KeycloakSelect";
|
||||
|
||||
const comparisonValues = ["exact", "minimum", "maximum", "better"];
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import type { ConfigPropertyRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigInfoRepresentation";
|
||||
import type ClientProfileRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientProfileRepresentation";
|
||||
import type ComponentTypeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentTypeRepresentation";
|
||||
import { HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
|
@ -18,10 +22,6 @@ import { useAdminClient } from "../admin-client";
|
|||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { DynamicComponents } from "../components/dynamic/DynamicComponents";
|
||||
import { FormAccess } from "../components/form/FormAccess";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../components/select/KeycloakSelect";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { useFetch } from "../utils/useFetch";
|
||||
|
|
|
@ -2,7 +2,11 @@ import type { ConfigPropertyRepresentation } from "@keycloak/keycloak-admin-clie
|
|||
import type ClientPolicyConditionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientPolicyConditionRepresentation";
|
||||
import type ClientPolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientPolicyRepresentation";
|
||||
import type ComponentTypeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentTypeRepresentation";
|
||||
import { HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
|
@ -20,10 +24,6 @@ import { useAdminClient } from "../admin-client";
|
|||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { DynamicComponents } from "../components/dynamic/DynamicComponents";
|
||||
import { FormAccess } from "../components/form/FormAccess";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../components/select/KeycloakSelect";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
|
|
|
@ -5,6 +5,7 @@ import type {
|
|||
PartialImportResult,
|
||||
} from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||
import { KeycloakSelect } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
@ -30,7 +31,6 @@ import { useTranslation } from "react-i18next";
|
|||
import { useAdminClient } from "../admin-client";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { JsonFileUpload } from "../components/json-file-upload/JsonFileUpload";
|
||||
import { KeycloakSelect } from "../components/select/KeycloakSelect";
|
||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -9,13 +14,7 @@ import {
|
|||
import { useEffect, useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
import { FormAccess } from "../components/form/FormAccess";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../components/select/KeycloakSelect";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { convertToFormValues } from "../util";
|
||||
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import {
|
||||
FormPanel,
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -17,8 +23,6 @@ import {
|
|||
import { useEffect, useState } from "react";
|
||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormPanel, HelpItem } from "@keycloak/keycloak-ui-shared";
|
||||
|
||||
import { FormAccess } from "../components/form/FormAccess";
|
||||
import {
|
||||
TimeSelector,
|
||||
|
@ -30,10 +34,6 @@ import { beerify, convertToFormValues, sortProviders } from "../util";
|
|||
import useIsFeatureEnabled, { Feature } from "../utils/useIsFeatureEnabled";
|
||||
|
||||
import "./realm-settings-section.css";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../components/select/KeycloakSelect";
|
||||
|
||||
type RealmSettingsSessionsTabProps = {
|
||||
realm: RealmRepresentation;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import type { KeyMetadataRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/keyMetadataRepresentation";
|
||||
import { KeycloakSelect, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
Button,
|
||||
ButtonVariant,
|
||||
|
@ -15,10 +16,6 @@ import { useAdminClient } from "../../admin-client";
|
|||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { emptyFormatter } from "../../util";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { KeycloakSelect, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -28,10 +29,6 @@ import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
|||
import { DEFAULT_LOCALE } from "../../i18n/i18n";
|
||||
import { localeToDisplayName } from "../../util";
|
||||
import useLocaleSort, { mapByKey } from "../../utils/useLocaleSort";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
type EffectiveMessageBundlesProps = {
|
||||
defaultSupportedLocales: string[];
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { KeycloakSelect, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
ButtonVariant,
|
||||
Divider,
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
DropdownList,
|
||||
Form,
|
||||
FormGroup,
|
||||
MenuToggle,
|
||||
SelectGroup,
|
||||
SelectOption,
|
||||
Text,
|
||||
TextContent,
|
||||
TextInput,
|
||||
TextVariants,
|
||||
ToolbarItem,
|
||||
SelectGroup,
|
||||
SelectOption,
|
||||
Dropdown,
|
||||
MenuToggle,
|
||||
DropdownList,
|
||||
DropdownItem,
|
||||
} from "@patternfly/react-core";
|
||||
import {
|
||||
CheckIcon,
|
||||
|
@ -51,10 +52,6 @@ import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
|||
import { DEFAULT_LOCALE } from "../../i18n/i18n";
|
||||
import { localeToDisplayName } from "../../util";
|
||||
import { AddTranslationModal } from "../AddTranslationModal";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
type RealmOverridesProps = {
|
||||
internationalizationEnabled: boolean;
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
NumberControl,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -8,14 +14,9 @@ import {
|
|||
import { useEffect, useState } from "react";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HelpItem, NumberControl } from "@keycloak/keycloak-ui-shared";
|
||||
import { FormAccess } from "../../components/form/FormAccess";
|
||||
import { convertToFormValues } from "../../util";
|
||||
import { Time } from "./Time";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
type BruteForceDetectionProps = {
|
||||
realm: RealmRepresentation;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { UserProfileAttribute } from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata";
|
||||
import { KeycloakSelect, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
Button,
|
||||
ButtonVariant,
|
||||
|
@ -13,20 +14,16 @@ import { uniqBy } from "lodash-es";
|
|||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
import { DraggableTable } from "../../authentication/components/DraggableTable";
|
||||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import useLocale from "../../utils/useLocale";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import { toAddAttribute } from "../routes/AddAttribute";
|
||||
import { toAttribute } from "../routes/Attribute";
|
||||
import { useUserProfile } from "./UserProfileContext";
|
||||
import useLocale from "../../utils/useLocale";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
const RESTRICTED_ATTRIBUTES = ["username", "email"];
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@ import type { UserProfileConfig } from "@keycloak/keycloak-admin-client/lib/defs
|
|||
import {
|
||||
FormErrorText,
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectControl,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
Alert,
|
||||
|
@ -30,10 +32,6 @@ import { useTranslation } from "react-i18next";
|
|||
import { useAdminClient } from "../../../admin-client";
|
||||
import { FormAccess } from "../../../components/form/FormAccess";
|
||||
import { KeycloakSpinner } from "../../../components/keycloak-spinner/KeycloakSpinner";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../../components/select/KeycloakSelect";
|
||||
import { useRealm } from "../../../context/realm-context/RealmContext";
|
||||
import { useFetch } from "../../../utils/useFetch";
|
||||
import { useParams } from "../../../utils/useParams";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import ComponentTypeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentTypeRepresentation";
|
||||
import { KeycloakSelect } from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { KeycloakSelect } from "../../../components/select/KeycloakSelect";
|
||||
import { useServerInfo } from "../../../context/server-info/ServerInfoProvider";
|
||||
import useToggle from "../../../utils/useToggle";
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import UserSessionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userSessionRepresentation";
|
||||
import { KeycloakSelect } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
DropdownItem,
|
||||
PageSection,
|
||||
|
@ -10,7 +11,6 @@ import { useTranslation } from "react-i18next";
|
|||
import { useAdminClient } from "../admin-client";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { KeycloakSelect } from "../components/select/KeycloakSelect";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { fetchAdminUI } from "../context/auth/admin-ui-endpoint";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
import type TestLdapConnectionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/testLdapConnection";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
PasswordControl,
|
||||
SelectControl,
|
||||
SelectVariant,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
AlertVariant,
|
||||
Button,
|
||||
|
@ -15,21 +23,11 @@ import {
|
|||
useWatch,
|
||||
} from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
HelpItem,
|
||||
PasswordControl,
|
||||
SelectControl,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { FormAccess } from "../../components/form/FormAccess";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
export type LdapSettingsConnectionProps = {
|
||||
form: UseFormReturn;
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { HelpItem, TextControl } from "@keycloak/keycloak-ui-shared";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Controller, FormProvider, UseFormReturn } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormAccess } from "../../components/form/FormAccess";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
export type LdapSettingsGeneralProps = {
|
||||
form: UseFormReturn<ComponentRepresentation>;
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import type ComponentTypeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentTypeRepresentation";
|
||||
import { DirectionType } from "@keycloak/keycloak-admin-client/lib/resources/userStorageProvider";
|
||||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
TextControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
|
@ -15,7 +21,6 @@ import { useState } from "react";
|
|||
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { HelpItem, TextControl } from "@keycloak/keycloak-ui-shared";
|
||||
import { useAdminClient } from "../../../admin-client";
|
||||
import { useAlerts } from "../../../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../../../components/confirm-dialog/ConfirmDialog";
|
||||
|
@ -32,10 +37,6 @@ import { useFetch } from "../../../utils/useFetch";
|
|||
import { useParams } from "../../../utils/useParams";
|
||||
import { toUserFederationLdap } from "../../routes/UserFederationLdap";
|
||||
import { UserFederationLdapMapperParams } from "../../routes/UserFederationLdapMapper";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../../components/select/KeycloakSelect";
|
||||
|
||||
export default function LdapMapperDetails() {
|
||||
const { adminClient } = useAdminClient();
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectControl,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, NumberInput, SelectOption } from "@patternfly/react-core";
|
||||
import { isEqual } from "lodash-es";
|
||||
import { Controller, UseFormReturn, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormAccess } from "../../components/form/FormAccess";
|
||||
import { HelpItem, SelectControl } from "@keycloak/keycloak-ui-shared";
|
||||
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
|
||||
import useToggle from "../../utils/useToggle";
|
||||
import {
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "../../components/select/KeycloakSelect";
|
||||
|
||||
export type SettingsCacheProps = {
|
||||
form: UseFormReturn;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { KeycloakSelect } from "@keycloak/keycloak-ui-shared";
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
|
@ -9,7 +10,6 @@ import {
|
|||
import { FilterIcon } from "@patternfly/react-icons";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { KeycloakSelect } from "../../components/select/KeycloakSelect";
|
||||
|
||||
export type SearchType = "default" | "attribute";
|
||||
|
||||
|
|
|
@ -39,13 +39,6 @@ export const SingleSelectControl = <
|
|||
} = useFormContext();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const convert = () =>
|
||||
options.map((option) => (
|
||||
<SelectOption key={key(option)} value={key(option)}>
|
||||
{isString(option) ? option : option.value}
|
||||
</SelectOption>
|
||||
));
|
||||
|
||||
return (
|
||||
<FormLabel
|
||||
name={name}
|
||||
|
@ -62,6 +55,7 @@ export const SingleSelectControl = <
|
|||
<Select
|
||||
{...rest}
|
||||
onClick={() => setOpen(!open)}
|
||||
onOpenChange={() => setOpen(false)}
|
||||
selected={
|
||||
isSelectBasedOptions(options)
|
||||
? options
|
||||
|
@ -84,28 +78,27 @@ export const SingleSelectControl = <
|
|||
aria-label="toggle"
|
||||
>
|
||||
{isSelectBasedOptions(options)
|
||||
? options.find((o) => o.key === value)?.value
|
||||
? options.find(
|
||||
(o) =>
|
||||
o.key === (Array.isArray(value) ? value[0] : value),
|
||||
)?.value
|
||||
: value}
|
||||
</MenuToggle>
|
||||
)}
|
||||
onSelect={(event, v) => {
|
||||
event?.stopPropagation();
|
||||
if (Array.isArray(value)) {
|
||||
onSelect={(_event, v) => {
|
||||
const option = v?.toString();
|
||||
const selected = key(option!);
|
||||
if (value.includes(key)) {
|
||||
onChange(value.filter((item: string) => item !== selected));
|
||||
} else {
|
||||
onChange([...value, option]);
|
||||
}
|
||||
} else {
|
||||
onChange(v);
|
||||
onChange(Array.isArray(value) ? [option] : option);
|
||||
setOpen(false);
|
||||
}
|
||||
}}
|
||||
isOpen={open}
|
||||
>
|
||||
<SelectList>{convert()}</SelectList>
|
||||
<SelectList>
|
||||
{options.map((option) => (
|
||||
<SelectOption key={key(option)} value={key(option)}>
|
||||
{isString(option) ? option : option.value}
|
||||
</SelectOption>
|
||||
))}
|
||||
</SelectList>
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -89,11 +89,14 @@ export const TypeaheadSelectControl = <
|
|||
|
||||
if (variant !== SelectVariant.typeaheadMulti) {
|
||||
setFilterValue(getValue(focusedItem));
|
||||
} else {
|
||||
setFilterValue("");
|
||||
}
|
||||
|
||||
field.onChange(
|
||||
Array.isArray(field.value)
|
||||
? [...field.value, getValue(focusedItem)]
|
||||
: getValue(focusedItem),
|
||||
? [...field.value, key(focusedItem)]
|
||||
: key(focusedItem),
|
||||
);
|
||||
setOpen(false);
|
||||
setFocusedItemIndex(0);
|
||||
|
@ -106,6 +109,12 @@ export const TypeaheadSelectControl = <
|
|||
field.onChange(undefined);
|
||||
break;
|
||||
}
|
||||
case "Backspace": {
|
||||
if (variant === SelectVariant.typeahead) {
|
||||
field.onChange("");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ArrowUp":
|
||||
case "ArrowDown": {
|
||||
event.preventDefault();
|
||||
|
@ -150,6 +159,7 @@ export const TypeaheadSelectControl = <
|
|||
<Select
|
||||
{...rest}
|
||||
onClick={() => setOpen(!open)}
|
||||
onOpenChange={() => setOpen(false)}
|
||||
selected={
|
||||
isSelectBasedOptions(options)
|
||||
? options
|
||||
|
@ -174,7 +184,19 @@ export const TypeaheadSelectControl = <
|
|||
<TextInputGroup isPlain>
|
||||
<TextInputGroupMain
|
||||
placeholder={placeholderText}
|
||||
value={filterValue}
|
||||
value={
|
||||
variant === SelectVariant.typeahead && field.value
|
||||
? isSelectBasedOptions(options)
|
||||
? options.find(
|
||||
(o) =>
|
||||
o.key ===
|
||||
(Array.isArray(field.value)
|
||||
? field.value[0]
|
||||
: field.value),
|
||||
)?.value
|
||||
: field.value
|
||||
: filterValue
|
||||
}
|
||||
onClick={() => setOpen(!open)}
|
||||
onChange={(_, value) => {
|
||||
setFilterValue(value);
|
||||
|
@ -234,21 +256,19 @@ export const TypeaheadSelectControl = <
|
|||
onSelect={(event, v) => {
|
||||
event?.stopPropagation();
|
||||
const option = v?.toString();
|
||||
if (Array.isArray(field.value)) {
|
||||
const select = key(option!);
|
||||
if (field.value.includes(key)) {
|
||||
if (
|
||||
variant === SelectVariant.typeaheadMulti &&
|
||||
Array.isArray(field.value)
|
||||
) {
|
||||
if (field.value.includes(option)) {
|
||||
field.onChange(
|
||||
field.value.filter((item: string) => item !== select),
|
||||
field.value.filter((item: string) => item !== option),
|
||||
);
|
||||
} else {
|
||||
field.onChange([...field.value, option]);
|
||||
}
|
||||
} else {
|
||||
const val = isSelectBasedOptions(options)
|
||||
? options.find((o) => o.key === option)?.value
|
||||
: option;
|
||||
field.onChange(val);
|
||||
setFilterValue(val || "");
|
||||
field.onChange(Array.isArray(field.value) ? [option] : option);
|
||||
setOpen(false);
|
||||
}
|
||||
}}
|
||||
|
|
|
@ -58,3 +58,5 @@ export { isDefined } from "./utils/isDefined";
|
|||
export { useRequiredContext } from "./utils/useRequiredContext";
|
||||
export { useStoredState } from "./utils/useStoredState";
|
||||
export { default as KeycloakMasthead } from "./masthead/Masthead";
|
||||
export { KeycloakSelect } from "./select/KeycloakSelect";
|
||||
export type { Variant, KeycloakSelectProps } from "./select/KeycloakSelect";
|
||||
|
|
|
@ -54,6 +54,7 @@ export const SingleSelect = ({
|
|||
}}
|
||||
{...props}
|
||||
onClick={toggle}
|
||||
onOpenChange={() => setOpen(false)}
|
||||
selected={selections}
|
||||
onSelect={(_, value) => {
|
||||
onSelect?.(value || "");
|
|
@ -75,6 +75,12 @@ export const TypeaheadSelect = ({
|
|||
onToggle?.(false);
|
||||
break;
|
||||
}
|
||||
case "Backspace": {
|
||||
if (variant === SelectVariant.typeahead) {
|
||||
onSelect?.("");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ArrowUp":
|
||||
case "ArrowDown": {
|
||||
event.preventDefault();
|
||||
|
@ -107,6 +113,7 @@ export const TypeaheadSelect = ({
|
|||
<Select
|
||||
{...rest}
|
||||
onClick={toggle}
|
||||
onOpenChange={() => onToggle?.(false)}
|
||||
onSelect={(_, value) => onSelect?.(value || "")}
|
||||
maxMenuHeight={propertyToString(maxHeight)}
|
||||
popperProps={{ direction, width: propertyToString(width) }}
|
||||
|
@ -124,7 +131,11 @@ export const TypeaheadSelect = ({
|
|||
<TextInputGroup isPlain>
|
||||
<TextInputGroupMain
|
||||
placeholder={placeholderText}
|
||||
value={filterValue}
|
||||
value={
|
||||
variant === SelectVariant.typeahead && selections
|
||||
? (selections as string)
|
||||
: filterValue
|
||||
}
|
||||
onClick={toggle}
|
||||
onChange={(_, value) => {
|
||||
setFilterValue(value);
|
||||
|
@ -165,6 +176,7 @@ export const TypeaheadSelect = ({
|
|||
onClick={() => {
|
||||
onSelect?.("");
|
||||
setFilterValue("");
|
||||
onFilter?.("");
|
||||
textInputRef?.current?.focus();
|
||||
}}
|
||||
aria-label="Clear input value"
|
|
@ -1,13 +1,7 @@
|
|||
import {
|
||||
Chip,
|
||||
ChipGroup,
|
||||
MenuToggle,
|
||||
Select,
|
||||
SelectList,
|
||||
SelectOption,
|
||||
} from "@patternfly/react-core";
|
||||
import { SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, ControllerRenderProps } from "react-hook-form";
|
||||
import { KeycloakSelect, SelectVariant } from "../select/KeycloakSelect";
|
||||
import {
|
||||
OptionLabel,
|
||||
Options,
|
||||
|
@ -19,6 +13,7 @@ import { UserFormFields, fieldName, label } from "./utils";
|
|||
export const SelectComponent = (props: UserProfileFieldProps) => {
|
||||
const { t, form, inputType, attribute } = props;
|
||||
const [open, setOpen] = useState(false);
|
||||
const [filter, setFilter] = useState("");
|
||||
const isMultiValue = inputType === "multiselect";
|
||||
|
||||
const setValue = (
|
||||
|
@ -36,7 +31,7 @@ export const SelectComponent = (props: UserProfileFieldProps) => {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
field.onChange(value);
|
||||
field.onChange(value === field.value ? "" : value);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -45,9 +40,25 @@ export const SelectComponent = (props: UserProfileFieldProps) => {
|
|||
|
||||
const optionLabel =
|
||||
(attribute.annotations?.["inputOptionLabels"] as OptionLabel) || {};
|
||||
|
||||
const fetchLabel = (option: string) =>
|
||||
label(props.t, optionLabel[option], option);
|
||||
|
||||
const convertOptions = (selected: string) =>
|
||||
options
|
||||
.filter((o) =>
|
||||
fetchLabel(o)!.toLowerCase().includes(filter.toLowerCase()),
|
||||
)
|
||||
.map((option) => (
|
||||
<SelectOption
|
||||
selected={selected === option}
|
||||
key={option}
|
||||
value={option}
|
||||
>
|
||||
{fetchLabel(option)}
|
||||
</SelectOption>
|
||||
));
|
||||
|
||||
return (
|
||||
<UserProfileGroup {...props}>
|
||||
<Controller
|
||||
|
@ -55,58 +66,39 @@ export const SelectComponent = (props: UserProfileFieldProps) => {
|
|||
defaultValue=""
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<Select
|
||||
toggle={(ref) => (
|
||||
<MenuToggle
|
||||
id={attribute.name}
|
||||
ref={ref}
|
||||
onClick={() => setOpen(!open)}
|
||||
isExpanded={open}
|
||||
isFullWidth
|
||||
isDisabled={attribute.readOnly}
|
||||
>
|
||||
{(isMultiValue && Array.isArray(field.value) ? (
|
||||
<ChipGroup>
|
||||
{field.value.map((selection, index: number) => (
|
||||
<Chip
|
||||
key={index}
|
||||
onClick={(ev) => {
|
||||
ev.stopPropagation();
|
||||
setValue(selection, field);
|
||||
}}
|
||||
>
|
||||
{selection}
|
||||
</Chip>
|
||||
))}
|
||||
</ChipGroup>
|
||||
) : (
|
||||
fetchLabel(field.value)
|
||||
)) || t("choose")}
|
||||
</MenuToggle>
|
||||
)}
|
||||
onSelect={(_, value) => {
|
||||
const option = value?.toString() || "";
|
||||
<KeycloakSelect
|
||||
toggleId={attribute.name}
|
||||
onToggle={(b) => setOpen(b)}
|
||||
onClear={() => setValue("", field)}
|
||||
onSelect={(value) => {
|
||||
const option = value.toString();
|
||||
setValue(option, field);
|
||||
if (!isMultiValue) {
|
||||
if (!Array.isArray(field.value)) {
|
||||
setOpen(false);
|
||||
}
|
||||
}}
|
||||
selected={field.value}
|
||||
selections={
|
||||
isMultiValue && Array.isArray(field.value)
|
||||
? field.value
|
||||
: fetchLabel(field.value)
|
||||
}
|
||||
variant={
|
||||
isMultiValue
|
||||
? SelectVariant.typeaheadMulti
|
||||
: options.length >= 10
|
||||
? SelectVariant.typeahead
|
||||
: SelectVariant.single
|
||||
}
|
||||
aria-label={t("selectOne")}
|
||||
isOpen={open}
|
||||
isDisabled={attribute.readOnly}
|
||||
onFilter={(value) => {
|
||||
setFilter(value);
|
||||
return convertOptions(field.value);
|
||||
}}
|
||||
>
|
||||
<SelectList>
|
||||
{options.map((option) => (
|
||||
<SelectOption
|
||||
selected={field.value === option}
|
||||
key={option}
|
||||
value={option}
|
||||
>
|
||||
{fetchLabel(option)}
|
||||
</SelectOption>
|
||||
))}
|
||||
</SelectList>
|
||||
</Select>
|
||||
{convertOptions(field.value)}
|
||||
</KeycloakSelect>
|
||||
)}
|
||||
/>
|
||||
</UserProfileGroup>
|
||||
|
|
Loading…
Reference in a new issue