From 131c50863ed2c158a432c83431f18d1987cb9182 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 2 Mar 2022 14:39:34 -0500 Subject: [PATCH] fix(striker-ui): only send changed properties when edit file --- striker-ui/components/Files/FileEditForm.tsx | 112 +++++++++++++++---- striker-ui/components/Files/FileInfo.tsx | 27 +++-- 2 files changed, 109 insertions(+), 30 deletions(-) diff --git a/striker-ui/components/Files/FileEditForm.tsx b/striker-ui/components/Files/FileEditForm.tsx index bf7cc13a..ff9b3b33 100644 --- a/striker-ui/components/Files/FileEditForm.tsx +++ b/striker-ui/components/Files/FileEditForm.tsx @@ -1,3 +1,4 @@ +import { AxiosResponse } from 'axios'; import { FormEventHandler, MouseEventHandler, @@ -17,6 +18,16 @@ import Spinner from '../Spinner'; import fetchJSON from '../../lib/fetchers/fetchJSON'; import mainAxiosInstance from '../../lib/singletons/mainAxiosInstance'; +type ReducedFileLocation = Partial< + Pick +>; + +type EditRequestContent = Partial< + Pick +> & { + fileLocations: ReducedFileLocation[]; +}; + type FileEditProps = { filesOverview: FileOverviewMetadata[]; onEditFilesComplete?: () => void; @@ -40,6 +51,9 @@ const FileEditForm = ( onPurgeFilesComplete, }: FileEditProps = FILE_EDIT_FORM_DEFAULT_PROPS as FileEditProps, ): JSX.Element => { + const [editRequestContents, setEditRequestContents] = useState< + EditRequestContent[] + >([]); const [filesToEdit, setFilesToEdit] = useState([]); const [isLoadingFilesToEdit, setIsLoadingFilesToEdit] = useState(false); @@ -57,14 +71,14 @@ const FileEditForm = ( const generateFileInfoChangeHandler = (fileIndex: number): FileInfoChangeHandler => (inputValues, { fileLocationIndex } = {}) => { - if (fileLocationIndex) { - filesToEdit[fileIndex].fileLocations[fileLocationIndex] = { - ...filesToEdit[fileIndex].fileLocations[fileLocationIndex], + if (fileLocationIndex !== undefined) { + editRequestContents[fileIndex].fileLocations[fileLocationIndex] = { + ...editRequestContents[fileIndex].fileLocations[fileLocationIndex], ...inputValues, }; } else { - filesToEdit[fileIndex] = { - ...filesToEdit[fileIndex], + editRequestContents[fileIndex] = { + ...editRequestContents[fileIndex], ...inputValues, }; } @@ -75,24 +89,61 @@ const FileEditForm = ( setIsLoadingFilesToEdit(true); - const editPromises = filesToEdit.map( - ({ fileLocations, fileName, fileType, fileUUID }) => - mainAxiosInstance.put( - `/files/${fileUUID}`, - JSON.stringify({ - fileName, - fileType, - fileLocations: fileLocations.map( - ({ fileLocationUUID, isFileLocationActive }) => ({ + const editPromises = editRequestContents.reduce[]>( + ( + reducedEditPromises, + { fileLocations, fileName, fileType, fileUUID }, + ) => { + const editRequestContent: Partial = {}; + + if (fileName !== undefined) { + editRequestContent.fileName = fileName; + } + + if (fileType !== undefined) { + editRequestContent.fileType = fileType; + } + + const changedFileLocations = fileLocations.reduce< + ReducedFileLocation[] + >( + ( + reducedFileLocations, + { fileLocationUUID, isFileLocationActive }, + ) => { + if (isFileLocationActive !== undefined) { + reducedFileLocations.push({ fileLocationUUID, isFileLocationActive, - }), - ), - }), - { - headers: { 'Content-Type': 'application/json' }, + }); + } + + return reducedFileLocations; }, - ), + [], + ); + + if (changedFileLocations.length > 0) { + editRequestContent.fileLocations = changedFileLocations; + } + + const stringEditFileRequestContent = JSON.stringify(editRequestContent); + + if (stringEditFileRequestContent !== '{}') { + reducedEditPromises.push( + mainAxiosInstance.put( + `/files/${fileUUID}`, + stringEditFileRequestContent, + { + headers: { 'Content-Type': 'application/json' }, + }, + ), + ); + } + + return reducedEditPromises; + }, + [], ); Promise.all(editPromises) @@ -180,6 +231,27 @@ const FileEditForm = ( }), ).then((fetchedFilesDetail) => { setFilesToEdit(fetchedFilesDetail); + + const initialEditRequestContents: EditRequestContent[] = []; + + for ( + let fileIndex = 0; + fileIndex < fetchedFilesDetail.length; + fileIndex += 1 + ) { + const fetchedFileDetail = fetchedFilesDetail[fileIndex]; + initialEditRequestContents.push({ + fileUUID: fetchedFileDetail.fileUUID, + fileLocations: fetchedFileDetail.fileLocations.map( + ({ fileLocationUUID }) => ({ + fileLocationUUID, + }), + ), + }); + } + + setEditRequestContents(initialEditRequestContents); + setIsLoadingFilesToEdit(false); }); }, [filesOverview]); diff --git a/striker-ui/components/Files/FileInfo.tsx b/striker-ui/components/Files/FileInfo.tsx index b348ac70..1144cc9b 100644 --- a/striker-ui/components/Files/FileInfo.tsx +++ b/striker-ui/components/Files/FileInfo.tsx @@ -93,9 +93,11 @@ const FileInfo = ( disabled={isReadonly} id={fileNameElementId} label={fileNameElementLabel} - onChange={({ target: { value } }) => - onChange?.call(null, { fileName: value }) - } + onChange={({ target: { value } }) => { + onChange?.call(null, { + fileName: value === fileName ? undefined : value, + }); + }} /> {fileType && ( @@ -108,9 +110,11 @@ const FileInfo = ( disabled={isReadonly} id={fileTypeElementId} input={} - onChange={({ target: { value } }) => - onChange?.call(null, { fileType: value as FileType }) - } + onChange={({ target: { value } }) => { + onChange?.call(null, { + fileType: value === fileType ? undefined : (value as FileType), + }); + }} > {UPLOAD_FILE_TYPES_ARRAY.map( ([fileTypeKey, [, fileTypeDisplayString]]) => { @@ -136,13 +140,16 @@ const FileInfo = ( defaultChecked={isFileLocationActive} disabled={isReadonly} icon={} - onChange={({ target: { checked } }) => + onChange={({ target: { checked } }) => { onChange?.call( null, - { isFileLocationActive: checked }, + { + isFileLocationActive: + checked === isFileLocationActive ? undefined : checked, + }, { fileLocationIndex }, - ) - } + ); + }} /> } key={anvilUUID}