import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Button, ButtonVariant, Chip, ChipGroup, InputGroup, PageSection, PageSectionVariants, Stack, StackItem, TextInput, ToolbarItem, } from "@patternfly/react-core"; import { SearchIcon } from "@patternfly/react-icons"; import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { useAdminClient } from "../context/auth/AdminClient"; import { useRealm } from "../context/realm-context/RealmContext"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { GroupPath } from "../components/group/GroupPath"; import { useSubGroups } from "./SubGroupsContext"; import { ViewHeader } from "../components/view-header/ViewHeader"; type SearchGroup = GroupRepresentation & { link?: string; }; export default function SearchGroups() { const { t } = useTranslation("groups"); const adminClient = useAdminClient(); const { realm } = useRealm(); const [searchTerm, setSearchTerm] = useState(""); const [searchTerms, setSearchTerms] = useState([]); const [key, setKey] = useState(0); const refresh = () => setKey(new Date().getTime()); const { setSubGroups } = useSubGroups(); useEffect( () => setSubGroups([{ name: t("searchGroups"), id: "search" }]), [] ); const deleteTerm = (id: string) => { const index = searchTerms.indexOf(id); searchTerms.splice(index, 1); setSearchTerms([...searchTerms]); refresh(); }; const addTerm = () => { if (searchTerm !== "") { setSearchTerms([...searchTerms, searchTerm]); setSearchTerm(""); refresh(); } }; const GroupNameCell = (group: SearchGroup) => ( setSubGroups([{ name: t("searchGroups"), id: "search" }, group]) } > {group.name} ); const flatten = ( groups: GroupRepresentation[], id?: string ): SearchGroup[] => { let result: SearchGroup[] = []; for (const group of groups) { const link = `${id || ""}${id ? "/" : ""}${group.id}`; result.push({ ...group, link }); if (group.subGroups) { result = [...result, ...flatten(group.subGroups, link)]; } } return result; }; const loader = async (first?: number, max?: number) => { const params = { first: first!, max: max!, }; let result: SearchGroup[] = []; if (searchTerms[0]) { result = await adminClient.groups.find({ ...params, search: searchTerms[0], }); result = flatten(result); for (const searchTerm of searchTerms) { result = result.filter((group) => group.name?.includes(searchTerm)); } } return result; }; const Path = (group: GroupRepresentation) => ; return ( <> setSearchTerm(value)} onKeyDown={(event) => { if (event.key === "Enter") { addTerm(); } }} /> {searchTerms.map((term) => ( deleteTerm(term)}> {term} ))} } ariaLabelKey="groups:groups" isPaginated loader={loader} columns={[ { name: "name", displayKey: "groups:groupName", cellRenderer: GroupNameCell, }, { name: "path", displayKey: "groups:path", cellRenderer: Path, }, ]} emptyState={ } /> ); }