1- import React , { useState , useEffect } from 'react' ;
1+ import React , { useState , useEffect , memo } from 'react' ;
22import { useUpdateEffect } from 'react-use' ;
33import { useDispatch } from 'react-redux' ;
44import equal from 'fast-deep-equal' ;
55import { getUniqueAndDublicates } from '@caesar/common/utils/file' ;
66import { PERMISSION } from '@caesar/common/constants' ;
7+ import { SCHEMA } from '@caesar/common/validation' ;
78import { isIterable } from '@caesar/common/utils/utils' ;
89import { processUploadedFiles } from '@caesar/common/utils/attachment' ;
910import {
@@ -30,94 +31,21 @@ const MODAL = {
3031 DELETE_FILE : 'delete_file' ,
3132} ;
3233
33- export const Attachments = ( {
34- itemId,
35- attachments = [ ] ,
36- raws = { } ,
37- itemSubject,
38- onClickAcceptEdit,
39- isVisibleDragZone,
40- } ) => {
41- const dispatch = useDispatch ( ) ;
42- const [ newFiles , setNewFiles ] = useState ( [ ] ) ;
43- const [ itemRaws , setItemRaws ] = useState ( raws ) ;
44- const [ itemAttachments , setItemAttachments ] = useState ( attachments ) ;
45- const [ openedModal , setOpenedModal ] = useState ( null ) ;
46-
47- const syncStateWithServer = newItemData => {
48- onClickAcceptEdit ( newItemData ) ;
49- } ;
50-
51- useUpdateEffect ( ( ) => {
52- if ( ! equal ( attachments , itemAttachments ) ) {
53- setItemAttachments ( attachments ) ;
54- }
55- } , [ attachments ] ) ;
56-
57- useEffect ( ( ) => {
58- if ( raws && Object . keys ( raws ) ?. length > 0 ) {
59- setItemRaws ( raws ) ;
60- }
61- } , [ raws , setItemRaws ] ) ; // This will only run when one of those variables change
62-
63- // TODO: Add loader if raws are not ready
64- const handleClickDownloadFile = attachment => {
65- dispatch ( downloadItemAttachment ( { itemId, attachment } ) ) ;
66- } ;
67-
68- const handleClickDownloadAll = ( ) => {
69- dispatch ( downloadItemAttachments ( { itemId } ) ) ;
70- } ;
71-
72- const onClickRemove = handleAttachment => {
73- const attachmentIndex = itemAttachments . findIndex (
74- attachment => attachment . id === handleAttachment . id ,
75- ) ;
76-
77- itemAttachments . splice ( attachmentIndex , 1 ) ;
78- delete itemRaws [ handleAttachment . id ] ;
79-
80- setItemAttachments ( itemAttachments ) ;
81- setItemRaws ( itemRaws ) ;
82- syncStateWithServer ( {
83- attachments : itemAttachments ,
84- raws : itemRaws ,
85- } ) ;
86- } ;
87-
88- const handleChange = ( name , files ) => {
89- const splitedFiles = processUploadedFiles ( files ) ;
90-
91- const { uniqNewFiles, duplicatedFiles } = getUniqueAndDublicates (
92- [ ...splitedFiles . attachments ] ,
93- [ ...itemAttachments ] ,
94- ) ;
95-
96- const uploadedDuplicatedFiles = duplicatedFiles . map ( file => ( {
97- ...file ,
98- error : 'The file already exists' ,
99- } ) ) ;
100-
101- const uniqNewRaws = Object . fromEntries (
102- uniqNewFiles . map ( file => [ file . id , splitedFiles . raws [ file . id ] ] ) ,
103- ) ;
104-
105- const allAttachments = [ ...itemAttachments , ...uniqNewFiles ] ;
106- const allRaws = { ...itemRaws , ...uniqNewRaws } ;
107-
108- setNewFiles ( [ ...uploadedDuplicatedFiles , ...uniqNewFiles ] ) ;
109-
110- setItemRaws ( allRaws ) ;
111- setItemAttachments ( allAttachments ) ;
112-
113- setOpenedModal ( MODAL . NEW_FILES ) ;
114- syncStateWithServer ( {
115- attachments : allAttachments ,
116- raws : allRaws ,
117- } ) ;
118- } ;
119-
120- const AttachmentsComponent = ( ) => (
34+ const AttachmentsComponent = memo (
35+ ( {
36+ attachments,
37+ itemAttachments,
38+ newFiles,
39+ itemSubject,
40+ isVisibleDragZone,
41+ openedModal,
42+ setOpenedModal,
43+ handleChange,
44+ handleClickDownloadAll,
45+ handleClickDownloadFile,
46+ onClickAcceptEdit,
47+ onClickRemove,
48+ } ) => (
12149 < Wrapper >
12250 < Title >
12351 Attachments ({ attachments ?. length ? attachments . length : 0 } )
@@ -202,13 +130,161 @@ export const Attachments = ({
202130 />
203131 ) }
204132 </ Wrapper >
205- ) ;
133+ ) ,
134+ ) ;
135+
136+ export const Attachments = ( {
137+ itemId,
138+ attachments = [ ] ,
139+ raws = { } ,
140+ itemSubject,
141+ onClickAcceptEdit,
142+ isVisibleDragZone,
143+ } ) => {
144+ const dispatch = useDispatch ( ) ;
145+ const [ newFiles , setNewFiles ] = useState ( [ ] ) ;
146+ const [ itemRaws , setItemRaws ] = useState ( raws ) ;
147+ const [ itemAttachments , setItemAttachments ] = useState ( attachments ) ;
148+ const [ openedModal , setOpenedModal ] = useState ( null ) ;
149+
150+ const syncStateWithServer = newItemData => {
151+ onClickAcceptEdit ( newItemData ) ;
152+ } ;
153+
154+ useUpdateEffect ( ( ) => {
155+ if ( ! equal ( attachments , itemAttachments ) ) {
156+ setItemAttachments ( attachments ) ;
157+ }
158+ } , [ attachments ] ) ;
159+
160+ useEffect ( ( ) => {
161+ if ( raws && Object . keys ( raws ) ?. length > 0 ) {
162+ setItemRaws ( raws ) ;
163+ }
164+ } , [ raws , setItemRaws ] ) ; // This will only run when one of those variables change
165+
166+ // TODO: Add loader if raws are not ready
167+ const handleClickDownloadFile = attachment => {
168+ dispatch ( downloadItemAttachment ( { itemId, attachment } ) ) ;
169+ } ;
170+
171+ const handleClickDownloadAll = ( ) => {
172+ dispatch ( downloadItemAttachments ( { itemId } ) ) ;
173+ } ;
174+
175+ const onClickRemove = handleAttachment => {
176+ const attachmentIndex = itemAttachments . findIndex (
177+ attachment => attachment . id === handleAttachment . id ,
178+ ) ;
179+
180+ itemAttachments . splice ( attachmentIndex , 1 ) ;
181+ delete itemRaws [ handleAttachment . id ] ;
182+
183+ setItemAttachments ( itemAttachments ) ;
184+ setItemRaws ( itemRaws ) ;
185+ syncStateWithServer ( {
186+ attachments : itemAttachments ,
187+ raws : itemRaws ,
188+ } ) ;
189+ } ;
190+
191+ const handleChange = ( name , files ) => {
192+ const splitedFiles = processUploadedFiles ( files ) ;
193+
194+ const {
195+ validated : validatedFiles ,
196+ errored : erroredFiles ,
197+ } = splitedFiles . attachments . reduce (
198+ ( acc , file ) => {
199+ try {
200+ SCHEMA . ATTACHMENT . validateSync ( file ) ;
201+ } catch ( error ) {
202+ // eslint-disable-next-line no-param-reassign
203+ file . error = error . message ;
204+ }
205+
206+ if ( file . error ) {
207+ return {
208+ ...acc ,
209+ errored : [ ...acc . errored , file ] ,
210+ } ;
211+ }
212+
213+ return {
214+ ...acc ,
215+ validated : [ ...acc . validated , file ] ,
216+ } ;
217+ } ,
218+ {
219+ validated : [ ] ,
220+ errored : [ ] ,
221+ } ,
222+ ) ;
223+
224+ const { uniqNewFiles, duplicatedFiles } = getUniqueAndDublicates (
225+ validatedFiles ,
226+ itemAttachments ,
227+ ) ;
228+
229+ const processedDuplicatedFiles = duplicatedFiles . map ( file => ( {
230+ ...file ,
231+ error : 'The file already exists' ,
232+ } ) ) ;
233+
234+ const uniqNewRaws = Object . fromEntries (
235+ uniqNewFiles . map ( file => [ file . id , splitedFiles . raws [ file . id ] ] ) ,
236+ ) ;
237+
238+ const allAttachments = [ ...itemAttachments , ...uniqNewFiles ] ;
239+ const allRaws = { ...itemRaws , ...uniqNewRaws } ;
240+
241+ setNewFiles ( [
242+ ...erroredFiles ,
243+ ...processedDuplicatedFiles ,
244+ ...uniqNewFiles ,
245+ ] ) ;
246+
247+ setItemRaws ( allRaws ) ;
248+ setItemAttachments ( allAttachments ) ;
249+
250+ setOpenedModal ( MODAL . NEW_FILES ) ;
251+ syncStateWithServer ( {
252+ attachments : allAttachments ,
253+ raws : allRaws ,
254+ } ) ;
255+ } ;
206256
207257 return Array . isArray ( itemAttachments ) && itemAttachments . length === 0 ? (
208258 < Can I = { PERMISSION . EDIT } an = { itemSubject } >
209- < AttachmentsComponent />
259+ < AttachmentsComponent
260+ attachments = { attachments }
261+ itemAttachments = { itemAttachments }
262+ newFiles = { newFiles }
263+ itemSubject = { itemSubject }
264+ isVisibleDragZone = { isVisibleDragZone }
265+ openedModal = { openedModal }
266+ setOpenedModal = { setOpenedModal }
267+ handleChange = { handleChange }
268+ handleClickDownloadAll = { handleClickDownloadAll }
269+ handleClickDownloadFile = { handleClickDownloadFile }
270+ onClickAcceptEdit = { onClickAcceptEdit }
271+ onClickRemove = { onClickRemove }
272+ />
210273 </ Can >
211274 ) : (
212- < AttachmentsComponent />
275+ < AttachmentsComponent
276+ attachments = { attachments }
277+ itemAttachments = { itemAttachments }
278+ newFiles = { newFiles }
279+ itemSubject = { itemSubject }
280+ isVisibleDragZone = { isVisibleDragZone }
281+ openedModal = { openedModal }
282+ setOpenedModal = { setOpenedModal }
283+ handleChange = { handleChange }
284+ handleClickDownloadAll = { handleClickDownloadAll }
285+ handleClickDownloadFile = { handleClickDownloadFile }
286+ onClickAcceptEdit = { onClickAcceptEdit }
287+ onClickRemove = { onClickRemove }
288+ />
213289 ) ;
214290} ;
0 commit comments