/* eslint-disable */ // @ts-nocheck import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation"; import { FormErrorText, HelpItem, useFetch, } from "../../../shared/keycloak-ui-shared"; import { Button, Chip, ChipGroup, FormGroup, MenuToggle, Select, SelectList, SelectOption, Spinner, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from "../../../shared/@patternfly/react-core"; import { TimesIcon } from "../../../shared/@patternfly/react-icons"; import { debounce } from "lodash-es"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Controller, useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useAdminClient } from "../../admin-client"; import useToggle from "../../utils/useToggle"; import type { ComponentProps } from "../dynamic/components"; type UserSelectVariant = "typeaheadMulti" | "typeahead"; type UserSelectProps = Omit & { variant?: UserSelectVariant; isRequired?: boolean; }; const USER_SEARCH_LIMIT = 20; const SHOW_MORE = "show-more"; export const UserSelect = ({ name, label, helpText, defaultValue, isRequired, variant = "typeaheadMulti", }: UserSelectProps) => { const { adminClient } = useAdminClient(); const { t } = useTranslation(); const { control, getValues, formState: { errors }, } = useFormContext(); const values: string[] | undefined = getValues(name!); const [open, toggleOpen, setOpen] = useToggle(); const [selectedUsers, setSelectedUsers] = useState([]); const [pageUsers, setPageUsers] = useState([]); const [exactMatch, setExactMatch] = useState(); const [first, setFirst] = useState(0); const [hasMore, setHasMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false); const [inputValue, setInputValue] = useState(""); const [search, setSearch] = useState(""); const textInputRef = useRef(); const debounceFn = useCallback( debounce((value: string) => { setFirst(0); setHasMore(false); setLoadingMore(false); setPageUsers([]); setExactMatch(undefined); setSearch(value); }, 500), [], ); useFetch( async () => { if (!values) { return []; } const foundUsers = await Promise.all( values.map((id) => adminClient.users.findOne({ id })), ); return foundUsers.filter((user) => user !== undefined); }, (users) => { setSelectedUsers(users); if (variant !== "typeaheadMulti") { setInputValue(users[0]?.username || ""); } }, [values], ); useFetch( () => adminClient.users.find({ username: search, first, max: USER_SEARCH_LIMIT + 1, }), (page) => { const more = page.length > USER_SEARCH_LIMIT; const nextUsers = more ? page.slice(0, USER_SEARCH_LIMIT) : page; setPageUsers((current) => first === 0 ? nextUsers : [...current, ...nextUsers], ); setHasMore(more); setLoadingMore(false); }, [search, first], ); useFetch( () => search ? adminClient.users.find({ username: search, exact: true, max: 1 }) : Promise.resolve([]), (matches) => setExactMatch(matches.at(0)), [search], ); useEffect(() => { if (!values || values.length === 0) { setSelectedUsers([]); setInputValue(""); } }, [values]); const searchedUsers = useMemo(() => { if (!exactMatch) { return pageUsers; } return [ exactMatch, ...pageUsers.filter((user) => user.id !== exactMatch.id), ]; }, [exactMatch, pageUsers]); const users = useMemo( () => [...selectedUsers, ...searchedUsers], [selectedUsers, searchedUsers], ); const convert = (users: UserRepresentation[]) => users.map((option) => ( {option.username} )); return ( } fieldId={name!} > value.length > 0 } : { required: isRequired } } render={({ field }) => ( )} /> {errors[name!] && } ); };