import { useFormik } from 'formik'; import { FC, useCallback, useMemo, useRef } from 'react'; import ActionGroup from '../ActionGroup'; import api from '../../lib/api'; import convertFormikErrorsToMessages from '../../lib/convertFormikErrorsToMessages'; import FileInputGroup from './FileInputGroup'; import FlexBox from '../FlexBox'; import handleAPIError from '../../lib/handleAPIError'; import MessageGroup, { MessageGroupForwardedRefContent } from '../MessageGroup'; import fileListSchema from './schema'; const toEditFileRequestBody = ( file: FileFormikFile, pfile: APIFileDetail, ): APIEditFileRequestBody | undefined => { const { locations, name: fileName, type: fileType, uuid: fileUUID } = file; if (!locations || !fileType) return undefined; const fileLocations: APIEditFileRequestBody['fileLocations'] = []; Object.entries(locations.anvils).reduce< APIEditFileRequestBody['fileLocations'] >((previous, [anvilUuid, { active: isFileLocationActive }]) => { const { anvils: { [anvilUuid]: { locationUuids }, }, } = pfile; const current = locationUuids.map< APIEditFileRequestBody['fileLocations'][number] >((fileLocationUUID) => ({ fileLocationUUID, isFileLocationActive, })); previous.push(...current); return previous; }, fileLocations); Object.entries(locations.drHosts).reduce< APIEditFileRequestBody['fileLocations'] >((previous, [drHostUuid, { active: isFileLocationActive }]) => { const { hosts: { [drHostUuid]: { locationUuids }, }, } = pfile; const current = locationUuids.map< APIEditFileRequestBody['fileLocations'][number] >((fileLocationUUID) => ({ fileLocationUUID, isFileLocationActive, })); previous.push(...current); return previous; }, fileLocations); return { fileLocations, fileName, fileType, fileUUID }; }; const EditFileForm: FC = (props) => { const { anvils, drHosts, onSuccess, previous: file } = props; const messageGroupRef = useRef({}); const setApiMessage = useCallback( (message?: Message) => messageGroupRef.current.setMessage?.call(null, 'api', message), [], ); const formikInitialValues = useMemo(() => { const { locations, name, type, uuid } = file; return { [uuid]: { locations: Object.values(locations).reduce( (previous, { active, anvilUuid, hostUuid }) => { let category: keyof FileFormikLocations = 'anvils'; let id = anvilUuid; if (hostUuid in drHosts) { category = 'drHosts'; id = hostUuid; } previous[category][id] = { active }; return previous; }, { anvils: {}, drHosts: {} }, ), name, type, uuid, }, }; }, [drHosts, file]); const formik = useFormik({ initialValues: formikInitialValues, onSubmit: (values, { setSubmitting }) => { const body = toEditFileRequestBody(values[file.uuid], file); api .put(`/file/${file.uuid}`, body) .then(() => { setApiMessage({ children: <>File updated. }); onSuccess?.call(null); }) .catch((error) => { const emsg = handleAPIError(error); emsg.children = <>Failed to modify file. {emsg.children}; setApiMessage(emsg); }) .finally(() => { setSubmitting(false); }); }, validationSchema: fileListSchema, }); const formikErrors = useMemo( () => convertFormikErrorsToMessages(formik.errors), [formik.errors], ); const disableProceed = useMemo( () => !formik.dirty || !formik.isValid || formik.isValidating || formik.isSubmitting, [formik.dirty, formik.isSubmitting, formik.isValid, formik.isValidating], ); return ( { event.preventDefault(); formik.submitForm(); }} > ); }; export default EditFileForm;