import React, { useEffect, useState } from "react"; import { ActionGroup, AlertVariant, Button, Chip, ChipGroup, FormGroup, InputGroup, Select, SelectOption, Switch, TextInput, } from "@patternfly/react-core"; import { useTranslation } from "react-i18next"; import { Controller, UseFormMethods } from "react-hook-form"; import { useHistory, useParams } from "react-router-dom"; import { FormAccess } from "../components/form-access/FormAccess"; import UserRepresentation from "keycloak-admin/lib/defs/userRepresentation"; import { HelpItem } from "../components/help-enabler/HelpItem"; import { useRealm } from "../context/realm-context/RealmContext"; import { asyncStateFetch, useAdminClient } from "../context/auth/AdminClient"; import { useErrorHandler } from "react-error-boundary"; import moment from "moment"; import { JoinGroupDialog } from "./JoinGroupDialog"; import GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation"; import { useAlerts } from "../components/alert/Alerts"; export type UserFormProps = { form: UseFormMethods; save: (user: UserRepresentation) => void; editMode: boolean; timestamp?: number; onGroupsUpdate: (groups: GroupRepresentation[]) => void; }; export const UserForm = ({ form: { handleSubmit, register, errors, watch, control, setValue, reset }, save, editMode, onGroupsUpdate, }: UserFormProps) => { const { t } = useTranslation("users"); const { realm } = useRealm(); const [ isRequiredUserActionsDropdownOpen, setRequiredUserActionsDropdownOpen, ] = useState(false); const history = useHistory(); const adminClient = useAdminClient(); const { id } = useParams<{ id: string }>(); const handleError = useErrorHandler(); const watchUsernameInput = watch("username"); const [timestamp, setTimestamp] = useState(null); const [chips, setChips] = useState<(string | undefined)[]>([]); const [selectedGroups, setSelectedGroups] = useState( [] ); const { addAlert } = useAlerts(); const [open, setOpen] = useState(false); useEffect(() => { if (editMode) { return asyncStateFetch( () => adminClient.users.findOne({ id: id }), (user) => { setupForm(user); }, handleError ); } }, [chips]); const setupForm = (user: UserRepresentation) => { reset(); Object.entries(user).map((entry) => { if (entry[0] == "createdTimestamp") { setTimestamp(entry[1]); } else { setValue(entry[0], entry[1]); } }); }; const emailRegexPattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const requiredUserActionsOptions = [ {t("configureOTP")} , {t("updatePassword")} , {t("updateProfile")} , {t("verifyEmail")} , ]; const clearSelection = () => { setRequiredUserActionsDropdownOpen(false); }; const deleteItem = (id: string) => { const copyOfChips = chips; const copyOfGroups = selectedGroups; setChips(copyOfChips.filter((item) => item !== id)); setSelectedGroups(copyOfGroups.filter((item) => item.name !== id)); onGroupsUpdate(selectedGroups); }; const addChips = async (groups: GroupRepresentation[]): Promise => { const newSelectedGroups = groups; const newGroupNames: (string | undefined)[] = newSelectedGroups!.map( (item) => item.name ); setChips([...chips!, ...newGroupNames]); setSelectedGroups([...selectedGroups!, ...newSelectedGroups]); }; onGroupsUpdate(selectedGroups); const addGroups = async (groups: GroupRepresentation[]): Promise => { const newGroups = groups; newGroups.forEach(async (group) => { try { await adminClient.users.addToGroup({ id: id, groupId: group.id!, }); addAlert(t("users:addedGroupMembership"), AlertVariant.success); } catch (error) { addAlert( t("users:addedGroupMembershipError", { error }), AlertVariant.danger ); } }); }; const toggleModal = () => { setOpen(!open); }; return ( {open && ( setOpen(!open)} onConfirm={editMode ? addGroups : addChips} toggleDialog={() => toggleModal()} chips={chips} /> )} {editMode ? ( <> ) : ( )} } > ( onChange(value)} isChecked={value} label={t("common:on")} labelOff={t("common:off")} /> )} > } > ( onChange(value)} isChecked={value} label={t("common:on")} labelOff={t("common:off")} /> )} > } > ( )} /> {!editMode && ( } > ( <> {chips.map((currentChip) => ( deleteItem(currentChip!)} > {currentChip} ))} )} /> )} ); };