mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
fixed when client select is a id instead of an clientId
fixes: #38929 (cherry picked from commit 025ee4ee6fe08b6cc76b6f5d8d25a3e1eac693b2) Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
parent
61fbcae818
commit
500c957462
@ -2,6 +2,7 @@ import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/
|
||||
import type { ClientQuery } from "@keycloak/keycloak-admin-client/lib/resources/clients";
|
||||
import {
|
||||
SelectControl,
|
||||
SelectControlOption,
|
||||
SelectVariant,
|
||||
useFetch,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
@ -11,6 +12,7 @@ import { useAdminClient } from "../../admin-client";
|
||||
import type { ComponentProps } from "../dynamic/components";
|
||||
import { PermissionsConfigurationTabsParams } from "../../permissions-configuration/routes/PermissionsConfigurationTabs";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useFormContext, useWatch } from "react-hook-form";
|
||||
|
||||
type ClientSelectProps = Omit<ComponentProps, "convertToName"> & {
|
||||
variant?: `${SelectVariant}`;
|
||||
@ -35,9 +37,18 @@ export const ClientSelect = ({
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [clients, setClients] = useState<ClientRepresentation[]>([]);
|
||||
const [selectedClients, setSelectedClients] =
|
||||
useState<SelectControlOption[]>();
|
||||
const [search, setSearch] = useState("");
|
||||
const { tab } = useParams<PermissionsConfigurationTabsParams>();
|
||||
|
||||
const { control } = useFormContext();
|
||||
const value = useWatch({
|
||||
control,
|
||||
name: name!,
|
||||
defaultValue: defaultValue || "",
|
||||
});
|
||||
|
||||
useFetch(
|
||||
() => {
|
||||
const params: ClientQuery = {
|
||||
@ -53,6 +64,30 @@ export const ClientSelect = ({
|
||||
[search],
|
||||
);
|
||||
|
||||
useFetch(
|
||||
() => {
|
||||
const values = ((value as string[]) || []).map(async (clientId) => {
|
||||
if (clientKey === "clientId") {
|
||||
return (await adminClient.clients.find({ clientId }))[0];
|
||||
} else {
|
||||
return adminClient.clients.findOne({ id: clientId });
|
||||
}
|
||||
});
|
||||
return Promise.all(values);
|
||||
},
|
||||
(clients) => {
|
||||
setSelectedClients(
|
||||
clients
|
||||
.filter((client) => !!client)
|
||||
.map((client) => ({
|
||||
key: client[clientKey] as string,
|
||||
value: client.clientId!,
|
||||
})),
|
||||
);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<SelectControl
|
||||
name={name!}
|
||||
@ -70,6 +105,7 @@ export const ClientSelect = ({
|
||||
onFilter={(value) => setSearch(value)}
|
||||
variant={variant}
|
||||
isDisabled={isDisabled}
|
||||
selectedOptions={selectedClients}
|
||||
options={clients.map((client) => ({
|
||||
key: client[clientKey] as string,
|
||||
value: client.clientId!,
|
||||
|
||||
@ -30,6 +30,7 @@ export async function fillEventListener(page: Page, listener: string) {
|
||||
await eventListener.click();
|
||||
await eventListener.fill(listener);
|
||||
await page.getByRole("option", { name: listener }).click();
|
||||
await page.keyboard.press("Escape");
|
||||
}
|
||||
|
||||
export async function clickRevertButton(page: Page) {
|
||||
|
||||
@ -41,6 +41,7 @@ export type SelectControlProps<
|
||||
name: string;
|
||||
label?: string;
|
||||
options: OptionType;
|
||||
selectedOptions?: SelectControlOption[];
|
||||
labelIcon?: string;
|
||||
controller: Omit<ControllerProps, "name" | "render">;
|
||||
onFilter?: (value: string) => void;
|
||||
|
||||
@ -43,6 +43,7 @@ export const TypeaheadSelectControl = <
|
||||
name,
|
||||
label,
|
||||
options,
|
||||
selectedOptions = [],
|
||||
controller,
|
||||
labelIcon,
|
||||
placeholderText,
|
||||
@ -57,6 +58,9 @@ export const TypeaheadSelectControl = <
|
||||
const [open, setOpen] = useState(false);
|
||||
const [filterValue, setFilterValue] = useState("");
|
||||
const [focusedItemIndex, setFocusedItemIndex] = useState<number>(0);
|
||||
const [selectedOptionsState, setSelectedOptions] = useState<
|
||||
SelectControlOption[]
|
||||
>([]);
|
||||
const textInputRef = useRef<HTMLInputElement>();
|
||||
const required = getRuleValue(controller.rules?.required) === true;
|
||||
const isTypeaheadMulti = variant === SelectVariant.typeaheadMulti;
|
||||
@ -79,6 +83,28 @@ export const TypeaheadSelectControl = <
|
||||
[focusedItemIndex, filteredOptions],
|
||||
);
|
||||
|
||||
const updateValue = (
|
||||
option: string | string[],
|
||||
field: ControllerRenderProps<FieldValues, string>,
|
||||
) => {
|
||||
if (field.value.includes(option)) {
|
||||
field.onChange(field.value.filter((item: string) => item !== option));
|
||||
if (isSelectBasedOptions(options)) {
|
||||
setSelectedOptions(
|
||||
selectedOptionsState.filter((item) => item.key !== option),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
field.onChange([...field.value, option]);
|
||||
if (isSelectBasedOptions(options)) {
|
||||
setSelectedOptions([
|
||||
...selectedOptionsState,
|
||||
options.find((o) => o.key === option)!,
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onInputKeyDown = (
|
||||
event: React.KeyboardEvent<HTMLDivElement>,
|
||||
field: ControllerRenderProps<FieldValues, string>,
|
||||
@ -96,11 +122,8 @@ export const TypeaheadSelectControl = <
|
||||
setFilterValue("");
|
||||
}
|
||||
|
||||
field.onChange(
|
||||
Array.isArray(field.value)
|
||||
? [...field.value, key(focusedItem)]
|
||||
: key(focusedItem),
|
||||
);
|
||||
updateValue(key(focusedItem), field);
|
||||
|
||||
setOpen(false);
|
||||
setFocusedItemIndex(0);
|
||||
|
||||
@ -232,8 +255,11 @@ export const TypeaheadSelectControl = <
|
||||
}}
|
||||
>
|
||||
{isSelectBasedOptions(options)
|
||||
? options.find((o) => selection === o.key)
|
||||
?.value
|
||||
? [
|
||||
...options,
|
||||
...selectedOptionsState,
|
||||
...selectedOptions,
|
||||
].find((o) => selection === o.key)?.value
|
||||
: getValue(selection)}
|
||||
</Chip>
|
||||
),
|
||||
@ -263,13 +289,8 @@ export const TypeaheadSelectControl = <
|
||||
event?.stopPropagation();
|
||||
const option = v?.toString();
|
||||
if (isTypeaheadMulti && Array.isArray(field.value)) {
|
||||
if (field.value.includes(option)) {
|
||||
field.onChange(
|
||||
field.value.filter((item: string) => item !== option),
|
||||
);
|
||||
} else {
|
||||
field.onChange([...field.value, option]);
|
||||
}
|
||||
setFilterValue("");
|
||||
updateValue(option || "", field);
|
||||
} else {
|
||||
field.onChange(Array.isArray(field.value) ? [option] : option);
|
||||
setOpen(false);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user