You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.6 KiB
180 lines
4.6 KiB
import { useFormik } from 'formik'; |
|
import { FC, useCallback, useMemo, useRef } from 'react'; |
|
|
|
import ActionGroup from '../ActionGroup'; |
|
import api from '../../lib/api'; |
|
import FileInputGroup from './FileInputGroup'; |
|
import FlexBox from '../FlexBox'; |
|
import getFormikErrorMessages from '../../lib/getFormikErrorMessages'; |
|
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<EditFileFormProps> = (props) => { |
|
const { anvils, drHosts, onSuccess, previous: file } = props; |
|
|
|
const messageGroupRef = useRef<MessageGroupForwardedRefContent>({}); |
|
|
|
const setApiMessage = useCallback( |
|
(message?: Message) => |
|
messageGroupRef.current.setMessage?.call(null, 'api', message), |
|
[], |
|
); |
|
|
|
const formikInitialValues = useMemo<FileFormikValues>(() => { |
|
const { locations, name, type, uuid } = file; |
|
|
|
return { |
|
[uuid]: { |
|
locations: Object.values(locations).reduce<FileFormikLocations>( |
|
(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<FileFormikValues>({ |
|
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<Messages>( |
|
() => getFormikErrorMessages(formik.errors), |
|
[formik.errors], |
|
); |
|
|
|
const disableProceed = useMemo<boolean>( |
|
() => |
|
!formik.dirty || |
|
!formik.isValid || |
|
formik.isValidating || |
|
formik.isSubmitting, |
|
[formik.dirty, formik.isSubmitting, formik.isValid, formik.isValidating], |
|
); |
|
|
|
return ( |
|
<FlexBox |
|
component="form" |
|
onSubmit={(event) => { |
|
event.preventDefault(); |
|
|
|
formik.submitForm(); |
|
}} |
|
> |
|
<FileInputGroup |
|
anvils={anvils} |
|
drHosts={drHosts} |
|
fileUuid={file.uuid} |
|
formik={formik} |
|
showSyncInputGroup |
|
showTypeInput |
|
/> |
|
<MessageGroup count={1} messages={formikErrors} ref={messageGroupRef} /> |
|
<ActionGroup |
|
loading={formik.isSubmitting} |
|
actions={[ |
|
{ |
|
background: 'blue', |
|
children: 'Edit', |
|
disabled: disableProceed, |
|
type: 'submit', |
|
}, |
|
]} |
|
/> |
|
</FlexBox> |
|
); |
|
}; |
|
|
|
export default EditFileForm;
|
|
|