import { FC, useMemo, useRef, useState } from 'react'; import API_BASE_URL from '../../lib/consts/API_BASE_URL'; import CommonUserInputGroup, { INPUT_ID_USER_CONFIRM_PASSWORD, INPUT_ID_USER_NAME, INPUT_ID_USER_PASSWORD, } from './CommonUserInputGroup'; import ConfirmDialog from '../ConfirmDialog'; import FormDialog from '../FormDialog'; import FormSummary from '../FormSummary'; import handleAPIError from '../../lib/handleAPIError'; import List from '../List'; import MessageBox, { Message } from '../MessageBox'; import MessageGroup, { MessageGroupForwardedRefContent } from '../MessageGroup'; import { ExpandablePanel } from '../Panels'; import periodicFetch from '../../lib/fetchers/periodicFetch'; import { BodyText } from '../Text'; import useChecklist from '../../hooks/useChecklist'; import useConfirmDialogProps from '../../hooks/useConfirmDialogProps'; import useFormUtils from '../../hooks/useFormUtils'; import useProtectedState from '../../hooks/useProtectedState'; const getFormEntries = ( ...[{ target }]: DivFormEventHandlerParameters ): CreateUserRequestBody => { const { elements } = target as HTMLFormElement; const { value: userName } = elements.namedItem( INPUT_ID_USER_NAME, ) as HTMLInputElement; const inputUserPassword = elements.namedItem(INPUT_ID_USER_PASSWORD); let password = ''; if (inputUserPassword) { ({ value: password } = inputUserPassword as HTMLInputElement); } return { password, userName }; }; const ManageUsersForm: FC = () => { const addUserFormDialogRef = useRef({}); const confirmDialogRef = useRef({}); const editUserFormDialogRef = useRef({}); const messageGroupRef = useRef({}); const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps(); const [editUsers, setEditUsers] = useState(false); const [listMessage, setListMessage] = useProtectedState({ children: `No users found.`, }); const [userDetail, setUserDetail] = useProtectedState< UserOverviewMetadata | undefined >(undefined); const { data: users, isLoading: loadingUsers } = periodicFetch(`${API_BASE_URL}/user`, { onError: (error) => { setListMessage(handleAPIError(error)); }, }); const formUtils = useFormUtils( [ INPUT_ID_USER_CONFIRM_PASSWORD, INPUT_ID_USER_NAME, INPUT_ID_USER_PASSWORD, ], messageGroupRef, ); const { isFormInvalid, isFormSubmitting, submitForm } = formUtils; const { buildDeleteDialogProps, checks, getCheck, hasChecks, setCheck } = useChecklist({ list: users }); const { userName: udetailName, userUUID: udetailUuid } = useMemo< Partial >(() => userDetail ?? {}, [userDetail]); const addUserFormDialogProps = useMemo( () => ({ actionProceedText: 'Add', content: ( ), onSubmitAppend: (...args) => { const body = getFormEntries(...args); setConfirmDialogProps({ actionProceedText: 'Add', content: , onProceedAppend: () => { submitForm({ body, getErrorMsg: (parentMsg) => <>Add user failed. {parentMsg}, method: 'post', successMsg: `Created user ${body.userName}.`, url: '/user', }); }, titleText: `Add the following new user?`, }); confirmDialogRef.current.setOpen?.call(null, true); }, titleText: 'Add a web interface user', }), [formUtils, setConfirmDialogProps, submitForm], ); const editUserFormDialogProps = useMemo( () => ({ actionProceedText: 'Edit', content: ( ), onSubmitAppend: (...args) => { const body = getFormEntries(...args); setConfirmDialogProps({ actionProceedText: 'Update', content: , onProceedAppend: () => { submitForm({ body, getErrorMsg: (parentMsg) => <>Update user failed. {parentMsg}, method: 'put', successMsg: `Updated user ${udetailName}`, url: `/user/${udetailUuid}`, }); }, titleText: `Update user ${udetailName} with the following?`, }); confirmDialogRef.current.setOpen?.call(null, true); }, titleText: `Edit user ${udetailName}`, }), [formUtils, setConfirmDialogProps, submitForm, udetailName, udetailUuid], ); const messageArea = useMemo( () => ( ), [], ); const allowModOthers = useMemo( () => users?.current?.userName === 'admin', [users], ); return ( <> ({ disabled: userName === 'admin', })} header listEmpty={} listItems={users} onAdd={() => { addUserFormDialogRef.current.setOpen?.call(null, true); }} onDelete={() => { setConfirmDialogProps( buildDeleteDialogProps({ confirmDialogProps: { onProceedAppend: () => { submitForm({ body: { uuids: checks }, getErrorMsg: (parentMsg) => ( <>Delete user(s) failed. {parentMsg} ), method: 'delete', url: '/user', }); }, }, formSummaryProps: { renderEntry: ({ key }) => ( {users?.[key].userName} ), }, getConfirmDialogTitle: (length) => `Delete the following ${length} users?`, }), ); confirmDialogRef.current.setOpen?.call(null, true); }} onEdit={() => setEditUsers((previous) => !previous)} onItemCheckboxChange={(key, event, checked) => setCheck(key, checked)} onItemClick={(value) => { if (editUsers) { setUserDetail(value); editUserFormDialogRef.current.setOpen?.call(null, true); } }} renderListItemCheckboxState={(key) => getCheck(key)} renderListItem={(userUUID, { userName }) => ( {userName} )} /> ); }; export default ManageUsersForm;