converted client select to ui-shared (#27799)
Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
parent
42244d2a67
commit
63bd46b8cd
2 changed files with 45 additions and 66 deletions
|
@ -1,15 +1,9 @@
|
|||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import type { ClientQuery } from "@keycloak/keycloak-admin-client/lib/resources/clients";
|
||||
import {
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
import { SelectVariant } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HelpItem } from "ui-shared";
|
||||
import { SelectControl } from "ui-shared";
|
||||
|
||||
import { adminClient } from "../../admin-client";
|
||||
import { useFetch } from "../../utils/useFetch";
|
||||
|
@ -26,12 +20,7 @@ export const ClientSelect = ({
|
|||
required = false,
|
||||
}: ClientSelectProps) => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
control,
|
||||
formState: { errors },
|
||||
} = useFormContext();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [clients, setClients] = useState<ClientRepresentation[]>([]);
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
|
@ -50,51 +39,27 @@ export const ClientSelect = ({
|
|||
[search],
|
||||
);
|
||||
|
||||
const convert = (clients: ClientRepresentation[]) => [
|
||||
<SelectOption key="empty" value="">
|
||||
{t("none")}
|
||||
</SelectOption>,
|
||||
...clients.map((option) => (
|
||||
<SelectOption key={option.id} value={option.clientId} />
|
||||
)),
|
||||
];
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
<SelectControl
|
||||
name={name!}
|
||||
label={t(label!)}
|
||||
isRequired={required}
|
||||
labelIcon={<HelpItem helpText={t(helpText!)} fieldLabelId={label!} />}
|
||||
fieldId={name!}
|
||||
validated={errors[name!] ? "error" : "default"}
|
||||
helperTextInvalid={t("required")}
|
||||
>
|
||||
<Controller
|
||||
name={name!}
|
||||
defaultValue={defaultValue || ""}
|
||||
control={control}
|
||||
rules={required ? { required: true } : {}}
|
||||
render={({ field }) => (
|
||||
<Select
|
||||
toggleId={name}
|
||||
variant={SelectVariant.typeahead}
|
||||
onToggle={(open) => setOpen(open)}
|
||||
isOpen={open}
|
||||
isDisabled={isDisabled}
|
||||
selections={field.value}
|
||||
onFilter={(_, value) => {
|
||||
setSearch(value);
|
||||
return convert(clients);
|
||||
}}
|
||||
onSelect={(_, value) => {
|
||||
field.onChange(value.toString());
|
||||
setOpen(false);
|
||||
}}
|
||||
typeAheadAriaLabel={t(label!)}
|
||||
>
|
||||
{convert(clients)}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
labelIcon={t(helpText!)}
|
||||
controller={{
|
||||
defaultValue: defaultValue || "",
|
||||
rules: {
|
||||
required: {
|
||||
value: required,
|
||||
message: t("required"),
|
||||
},
|
||||
},
|
||||
}}
|
||||
onFilter={(value) => setSearch(value)}
|
||||
variant={SelectVariant.typeahead}
|
||||
isDisabled={isDisabled}
|
||||
options={[
|
||||
{ key: "", value: t("none") },
|
||||
...clients.map(({ id, clientId }) => ({ key: id!, value: clientId! })),
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -26,7 +26,13 @@ export type SelectControlProps<
|
|||
P extends FieldPath<T> = FieldPath<T>,
|
||||
> = Omit<
|
||||
SelectProps,
|
||||
"name" | "onToggle" | "selections" | "onSelect" | "onClear" | "isOpen"
|
||||
| "name"
|
||||
| "onToggle"
|
||||
| "selections"
|
||||
| "onSelect"
|
||||
| "onClear"
|
||||
| "isOpen"
|
||||
| "onFilter"
|
||||
> &
|
||||
UseControllerProps<T, P> & {
|
||||
name: string;
|
||||
|
@ -34,6 +40,7 @@ export type SelectControlProps<
|
|||
options: string[] | SelectControlOption[];
|
||||
labelIcon?: string;
|
||||
controller: Omit<ControllerProps, "name" | "render">;
|
||||
onFilter?: (value: string) => void;
|
||||
};
|
||||
|
||||
export const SelectControl = <
|
||||
|
@ -46,6 +53,7 @@ export const SelectControl = <
|
|||
controller,
|
||||
variant = SelectVariant.single,
|
||||
labelIcon,
|
||||
onFilter,
|
||||
...rest
|
||||
}: SelectControlProps<T, P>) => {
|
||||
const {
|
||||
|
@ -53,6 +61,15 @@ export const SelectControl = <
|
|||
formState: { errors },
|
||||
} = useFormContext();
|
||||
const [open, setOpen] = useState(false);
|
||||
const convert = () =>
|
||||
options.map((option) => (
|
||||
<SelectOption
|
||||
key={typeof option === "string" ? option : option.key}
|
||||
value={typeof option === "string" ? option : option.key}
|
||||
>
|
||||
{typeof option === "string" ? option : option.value}
|
||||
</SelectOption>
|
||||
));
|
||||
return (
|
||||
<FormLabel
|
||||
name={name}
|
||||
|
@ -98,20 +115,17 @@ export const SelectControl = <
|
|||
}
|
||||
: undefined
|
||||
}
|
||||
onFilter={(_, value) => {
|
||||
onFilter?.(value);
|
||||
return convert();
|
||||
}}
|
||||
isOpen={open}
|
||||
variant={variant}
|
||||
validated={
|
||||
errors[name] ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<SelectOption
|
||||
key={typeof option === "string" ? option : option.key}
|
||||
value={typeof option === "string" ? option : option.key}
|
||||
>
|
||||
{typeof option === "string" ? option : option.value}
|
||||
</SelectOption>
|
||||
))}
|
||||
{convert()}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
|
|
Loading…
Reference in a new issue