@akemona-org/strapi-plugin-upload 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +19 -0
  3. package/admin/src/assets/images/logo.svg +1 -0
  4. package/admin/src/components/BrowseAssets/Wrapper.js +8 -0
  5. package/admin/src/components/BrowseAssets/index.js +182 -0
  6. package/admin/src/components/Card/index.js +146 -0
  7. package/admin/src/components/CardBorder/index.js +28 -0
  8. package/admin/src/components/CardControl/Wrapper.js +89 -0
  9. package/admin/src/components/CardControl/index.js +61 -0
  10. package/admin/src/components/CardControlsWrapper/index.js +22 -0
  11. package/admin/src/components/CardEmpty/Bar.js +19 -0
  12. package/admin/src/components/CardEmpty/Wrapper.js +7 -0
  13. package/admin/src/components/CardEmpty/index.js +16 -0
  14. package/admin/src/components/CardErrorMessage/index.js +9 -0
  15. package/admin/src/components/CardImgWrapper/index.js +52 -0
  16. package/admin/src/components/CardPreview/Image.js +12 -0
  17. package/admin/src/components/CardPreview/Wrapper.js +25 -0
  18. package/admin/src/components/CardPreview/index.js +66 -0
  19. package/admin/src/components/CardTitle/index.js +14 -0
  20. package/admin/src/components/CardWrapper/index.js +23 -0
  21. package/admin/src/components/CheckControl/Button.js +49 -0
  22. package/admin/src/components/CheckControl/CustomDropdownSection.js +9 -0
  23. package/admin/src/components/CheckControl/Spacer.js +7 -0
  24. package/admin/src/components/CheckControl/index.js +74 -0
  25. package/admin/src/components/Container/index.js +7 -0
  26. package/admin/src/components/ContainerFluid/index.js +12 -0
  27. package/admin/src/components/ControlsWrapper/index.js +9 -0
  28. package/admin/src/components/DragLayer/Wrapper.js +13 -0
  29. package/admin/src/components/DragLayer/index.js +68 -0
  30. package/admin/src/components/DropdownButton/index.js +63 -0
  31. package/admin/src/components/DropdownSection/index.js +27 -0
  32. package/admin/src/components/Duration/index.js +25 -0
  33. package/admin/src/components/Duration/utils/formatDuration.js +13 -0
  34. package/admin/src/components/EditForm/CropWrapper.js +21 -0
  35. package/admin/src/components/EditForm/ErrorMessage.js +10 -0
  36. package/admin/src/components/EditForm/FileDetailsBox.js +95 -0
  37. package/admin/src/components/EditForm/FileDetailsBoxWrapper.js +14 -0
  38. package/admin/src/components/EditForm/FileWrapper.js +41 -0
  39. package/admin/src/components/EditForm/FormWrapper.js +7 -0
  40. package/admin/src/components/EditForm/SizeBox.js +13 -0
  41. package/admin/src/components/EditForm/Wrapper.js +8 -0
  42. package/admin/src/components/EditForm/index.js +425 -0
  43. package/admin/src/components/EditForm/utils/form.js +34 -0
  44. package/admin/src/components/EditForm/utils/isImageType.js +3 -0
  45. package/admin/src/components/EditForm/utils/isVideoType.js +3 -0
  46. package/admin/src/components/FileIcon/Wrapper.js +20 -0
  47. package/admin/src/components/FileIcon/index.js +33 -0
  48. package/admin/src/components/FileIcon/utils/extensions.json +4 -0
  49. package/admin/src/components/FileInfos/index.js +32 -0
  50. package/admin/src/components/Filters/index.js +30 -0
  51. package/admin/src/components/FiltersList/index.js +34 -0
  52. package/admin/src/components/FiltersList/utils/formatFilter.js +36 -0
  53. package/admin/src/components/FiltersPicker/FiltersCard/FilterButton.js +8 -0
  54. package/admin/src/components/FiltersPicker/FiltersCard/FilterInput.js +35 -0
  55. package/admin/src/components/FiltersPicker/FiltersCard/InputWrapper.js +10 -0
  56. package/admin/src/components/FiltersPicker/FiltersCard/SizeInput.js +57 -0
  57. package/admin/src/components/FiltersPicker/FiltersCard/Wrapper.js +8 -0
  58. package/admin/src/components/FiltersPicker/FiltersCard/index.js +97 -0
  59. package/admin/src/components/FiltersPicker/FiltersCard/init.js +21 -0
  60. package/admin/src/components/FiltersPicker/FiltersCard/reducer.js +47 -0
  61. package/admin/src/components/FiltersPicker/FiltersCard/utils/filtersForm.js +27 -0
  62. package/admin/src/components/FiltersPicker/index.js +43 -0
  63. package/admin/src/components/FiltersPicker/utils/formatFilter.js +18 -0
  64. package/admin/src/components/InfiniteLoadingIndicator/Button.js +20 -0
  65. package/admin/src/components/InfiniteLoadingIndicator/Container.js +12 -0
  66. package/admin/src/components/InfiniteLoadingIndicator/Wrapper.js +18 -0
  67. package/admin/src/components/InfiniteLoadingIndicator/index.js +39 -0
  68. package/admin/src/components/Input/index.js +7 -0
  69. package/admin/src/components/InputFileModal/Label.js +47 -0
  70. package/admin/src/components/InputFileModal/P.js +15 -0
  71. package/admin/src/components/InputFileModal/index.js +73 -0
  72. package/admin/src/components/InputMedia/CardControlWrapper.js +12 -0
  73. package/admin/src/components/InputMedia/CardPreviewWrapper.js +13 -0
  74. package/admin/src/components/InputMedia/Chevron/Wrapper.js +10 -0
  75. package/admin/src/components/InputMedia/Chevron/index.js +21 -0
  76. package/admin/src/components/InputMedia/EmptyInputMedia.js +60 -0
  77. package/admin/src/components/InputMedia/EmptyText.js +13 -0
  78. package/admin/src/components/InputMedia/ErrorMessage.js +12 -0
  79. package/admin/src/components/InputMedia/IconUpload.js +48 -0
  80. package/admin/src/components/InputMedia/InputFilePreview.js +37 -0
  81. package/admin/src/components/InputMedia/Name.js +10 -0
  82. package/admin/src/components/InputMedia/Wrapper.js +11 -0
  83. package/admin/src/components/InputMedia/index.js +238 -0
  84. package/admin/src/components/InputUploadURL/Wrapper.js +13 -0
  85. package/admin/src/components/InputUploadURL/index.js +46 -0
  86. package/admin/src/components/IntlText/index.js +26 -0
  87. package/admin/src/components/List/ListCell.js +19 -0
  88. package/admin/src/components/List/ListRow.js +8 -0
  89. package/admin/src/components/List/index.js +114 -0
  90. package/admin/src/components/ListEmpty/Wrapper.js +15 -0
  91. package/admin/src/components/ListEmpty/index.js +70 -0
  92. package/admin/src/components/ListEmpty/utils/generateRows.js +12 -0
  93. package/admin/src/components/ListModal/BaselineAlignmentWrapper.js +12 -0
  94. package/admin/src/components/ListModal/index.js +66 -0
  95. package/admin/src/components/ListWrapper/index.js +16 -0
  96. package/admin/src/components/LoadingIndicator/index.js +44 -0
  97. package/admin/src/components/ModalHeader/BackButton.js +33 -0
  98. package/admin/src/components/ModalHeader/Wrapper.js +24 -0
  99. package/admin/src/components/ModalHeader/index.js +47 -0
  100. package/admin/src/components/ModalNavWrapper/BaselineAlignment.js +12 -0
  101. package/admin/src/components/ModalNavWrapper/Hr.js +14 -0
  102. package/admin/src/components/ModalNavWrapper/Wrapper.js +8 -0
  103. package/admin/src/components/ModalNavWrapper/index.js +70 -0
  104. package/admin/src/components/ModalSection/index.js +20 -0
  105. package/admin/src/components/ModalTab/Count/Wrapper.js +16 -0
  106. package/admin/src/components/ModalTab/Count/index.js +30 -0
  107. package/admin/src/components/ModalTab/Wrapper.js +37 -0
  108. package/admin/src/components/ModalTab/index.js +60 -0
  109. package/admin/src/components/PlayIcon/Play.js +65 -0
  110. package/admin/src/components/PlayIcon/Wrapper.js +24 -0
  111. package/admin/src/components/PlayIcon/index.js +23 -0
  112. package/admin/src/components/SelectAll/Wrapper.js +19 -0
  113. package/admin/src/components/SelectAll/index.js +26 -0
  114. package/admin/src/components/SelectedAssets/DraggableCard.js +149 -0
  115. package/admin/src/components/SelectedAssets/ListTitleWrapper.js +7 -0
  116. package/admin/src/components/SelectedAssets/ListWrapper.js +7 -0
  117. package/admin/src/components/SelectedAssets/SortableList.js +102 -0
  118. package/admin/src/components/SelectedAssets/Wrapper.js +7 -0
  119. package/admin/src/components/SelectedAssets/index.js +56 -0
  120. package/admin/src/components/SortList/Wrapper.js +19 -0
  121. package/admin/src/components/SortList/index.js +37 -0
  122. package/admin/src/components/SortListItem/Wrapper.js +28 -0
  123. package/admin/src/components/SortListItem/index.js +35 -0
  124. package/admin/src/components/SortPicker/index.js +54 -0
  125. package/admin/src/components/Tag/Wrapper.js +16 -0
  126. package/admin/src/components/Tag/index.js +25 -0
  127. package/admin/src/components/UploadForm/index.js +61 -0
  128. package/admin/src/components/UploadList/ButtonWrapper.js +7 -0
  129. package/admin/src/components/UploadList/Container.js +10 -0
  130. package/admin/src/components/UploadList/CustomModalSection.js +9 -0
  131. package/admin/src/components/UploadList/ListTitle.js +10 -0
  132. package/admin/src/components/UploadList/ListTitleWrapper.js +7 -0
  133. package/admin/src/components/UploadList/RowItem.js +98 -0
  134. package/admin/src/components/UploadList/index.js +90 -0
  135. package/admin/src/components/VideoPlayer/Wrapper.js +24 -0
  136. package/admin/src/components/VideoPlayer/index.js +57 -0
  137. package/admin/src/components/VideoPreview/CanvasWrapper.js +22 -0
  138. package/admin/src/components/VideoPreview/Thumbnail.js +12 -0
  139. package/admin/src/components/VideoPreview/Wrapper.js +15 -0
  140. package/admin/src/components/VideoPreview/index.js +165 -0
  141. package/admin/src/components/VideoPreview/reducer.js +33 -0
  142. package/admin/src/containers/App/index.js +31 -0
  143. package/admin/src/containers/HomePage/HomePageContent/HomePageList.js +98 -0
  144. package/admin/src/containers/HomePage/HomePageContent/HomePageSettings.js +103 -0
  145. package/admin/src/containers/HomePage/HomePageContent/index.js +90 -0
  146. package/admin/src/containers/HomePage/components.js +18 -0
  147. package/admin/src/containers/HomePage/index.js +373 -0
  148. package/admin/src/containers/HomePage/init.js +5 -0
  149. package/admin/src/containers/HomePage/reducer.js +88 -0
  150. package/admin/src/containers/HomePage/utils/generateParamsFromQuery.js +14 -0
  151. package/admin/src/containers/HomePage/utils/generateStringFromParams.js +27 -0
  152. package/admin/src/containers/HomePage/utils/getHeaderLabel.js +13 -0
  153. package/admin/src/containers/HomePage/utils/index.js +2 -0
  154. package/admin/src/containers/Initializer/index.js +44 -0
  155. package/admin/src/containers/InputModalStepper/HeaderSearch.js +12 -0
  156. package/admin/src/containers/InputModalStepper/InputModalStepper.js +480 -0
  157. package/admin/src/containers/InputModalStepper/Search.js +48 -0
  158. package/admin/src/containers/InputModalStepper/index.js +86 -0
  159. package/admin/src/containers/InputModalStepper/stepper.js +52 -0
  160. package/admin/src/containers/InputModalStepperProvider/index.js +564 -0
  161. package/admin/src/containers/InputModalStepperProvider/init.js +5 -0
  162. package/admin/src/containers/InputModalStepperProvider/reducer.js +301 -0
  163. package/admin/src/containers/ModalStepper/index.js +629 -0
  164. package/admin/src/containers/ModalStepper/init.js +5 -0
  165. package/admin/src/containers/ModalStepper/reducer.js +132 -0
  166. package/admin/src/containers/ModalStepper/stepper.js +46 -0
  167. package/admin/src/containers/SettingsPage/Divider.js +11 -0
  168. package/admin/src/containers/SettingsPage/SectionTitleWrapper.js +7 -0
  169. package/admin/src/containers/SettingsPage/Wrapper.js +17 -0
  170. package/admin/src/containers/SettingsPage/index.js +198 -0
  171. package/admin/src/containers/SettingsPage/init.js +5 -0
  172. package/admin/src/containers/SettingsPage/reducer.js +38 -0
  173. package/admin/src/contexts/AppContext/index.js +5 -0
  174. package/admin/src/contexts/InputModal/InputModalDataManager.js +5 -0
  175. package/admin/src/contexts/index.js +2 -0
  176. package/admin/src/hooks/index.js +2 -0
  177. package/admin/src/hooks/useAppContext/index.js +6 -0
  178. package/admin/src/hooks/useModalContext.js +6 -0
  179. package/admin/src/icons/BrokenFile/index.js +91 -0
  180. package/admin/src/icons/Cloud/index.js +35 -0
  181. package/admin/src/icons/DoubleFile/index.js +35 -0
  182. package/admin/src/icons/Download/index.js +36 -0
  183. package/admin/src/icons/File/index.js +35 -0
  184. package/admin/src/index.js +85 -0
  185. package/admin/src/lifecycles.js +13 -0
  186. package/admin/src/permissions.js +40 -0
  187. package/admin/src/pluginId.js +5 -0
  188. package/admin/src/translations/de.json +81 -0
  189. package/admin/src/translations/dk.json +81 -0
  190. package/admin/src/translations/en.json +86 -0
  191. package/admin/src/translations/es.json +81 -0
  192. package/admin/src/translations/fr.json +85 -0
  193. package/admin/src/translations/he.json +81 -0
  194. package/admin/src/translations/index.js +39 -0
  195. package/admin/src/translations/it.json +82 -0
  196. package/admin/src/translations/ja.json +81 -0
  197. package/admin/src/translations/ms.json +73 -0
  198. package/admin/src/translations/pl.json +81 -0
  199. package/admin/src/translations/pt-BR.json +81 -0
  200. package/admin/src/translations/ru.json +81 -0
  201. package/admin/src/translations/sk.json +81 -0
  202. package/admin/src/translations/th.json +81 -0
  203. package/admin/src/translations/uk.json +78 -0
  204. package/admin/src/translations/zh-Hans.json +86 -0
  205. package/admin/src/translations/zh.json +81 -0
  206. package/admin/src/utils/ItemTypes.js +3 -0
  207. package/admin/src/utils/canDownloadFile.js +3 -0
  208. package/admin/src/utils/compactParams.js +13 -0
  209. package/admin/src/utils/createFileToDownloadName.js +9 -0
  210. package/admin/src/utils/createMatrix.js +32 -0
  211. package/admin/src/utils/createNewFilesToDownloadArray.js +57 -0
  212. package/admin/src/utils/createNewFilesToUploadArray.js +25 -0
  213. package/admin/src/utils/formatBytes.js +13 -0
  214. package/admin/src/utils/formatFileForEditing.js +20 -0
  215. package/admin/src/utils/formatFilters.js +23 -0
  216. package/admin/src/utils/generatePageFromStart.js +5 -0
  217. package/admin/src/utils/generateStartFromPage.js +5 -0
  218. package/admin/src/utils/getFileModelTimestamps.js +15 -0
  219. package/admin/src/utils/getFilesToDownload.js +5 -0
  220. package/admin/src/utils/getRequestUrl.js +5 -0
  221. package/admin/src/utils/getTrad.js +5 -0
  222. package/admin/src/utils/getType.js +15 -0
  223. package/admin/src/utils/getYupError.js +17 -0
  224. package/admin/src/utils/index.js +20 -0
  225. package/admin/src/utils/unformatBytes.js +16 -0
  226. package/admin/src/utils/urlYupSchema.js +49 -0
  227. package/config/config.json +8 -0
  228. package/config/functions/bootstrap.js +143 -0
  229. package/config/routes.json +98 -0
  230. package/config/schema.graphql.js +96 -0
  231. package/controllers/Upload.js +103 -0
  232. package/controllers/upload/admin.js +213 -0
  233. package/controllers/upload/api.js +125 -0
  234. package/controllers/validation/settings.js +22 -0
  235. package/controllers/validation/upload.js +27 -0
  236. package/documentation/1.0.0/overrides/upload-File.json +263 -0
  237. package/errors.js +48 -0
  238. package/index.js +7 -0
  239. package/middlewares/upload/defaults.json +5 -0
  240. package/middlewares/upload/index.js +35 -0
  241. package/models/File.js +7 -0
  242. package/models/File.settings.json +86 -0
  243. package/package.json +71 -0
  244. package/services/Upload.js +397 -0
  245. package/services/image-manipulation.js +167 -0
  246. package/utils/file.js +23 -0
@@ -0,0 +1,480 @@
1
+ import React, { useEffect, useState, useRef, memo } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Modal, ModalFooter, PopUpWarning, useGlobalContext, request } from 'strapi-helper-plugin';
4
+ import { Button } from '@buffetjs/core';
5
+ import { get, isEmpty, isEqual } from 'lodash';
6
+ import { getRequestUrl, getTrad } from '../../utils';
7
+ import ModalHeader from '../../components/ModalHeader';
8
+ import pluginId from '../../pluginId';
9
+ import stepper from './stepper';
10
+ import useModalContext from '../../hooks/useModalContext';
11
+
12
+ const InputModalStepper = ({
13
+ allowedActions,
14
+ isOpen,
15
+ onToggle,
16
+ noNavigation,
17
+ onInputMediaChange,
18
+ }) => {
19
+ const { emitEvent, formatMessage } = useGlobalContext();
20
+ const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
21
+ const [displayNextButton, setDisplayNextButton] = useState(false);
22
+ const {
23
+ addFilesToUpload,
24
+ currentStep,
25
+ downloadFiles,
26
+ fetchMediaLib,
27
+ filesToDownload,
28
+ filesToUpload,
29
+ fileToEdit,
30
+ formErrors,
31
+ goTo,
32
+ handleAbortUpload,
33
+ handleCancelFileToUpload,
34
+ handleCleanFilesError,
35
+ handleClearFilesToUploadAndDownload,
36
+ handleClickNextButton,
37
+ handleClose,
38
+ handleEditExistingFile,
39
+ handleFileSelection,
40
+ handleFileToEditChange,
41
+ handleFormDisabled,
42
+ handleGoToEditNewFile,
43
+ handleRemoveFileToUpload,
44
+ handleResetFileToEdit,
45
+ handleSetCropResult,
46
+ handleSetFileToEditError,
47
+ handleUploadFiles,
48
+ initialFileToEdit,
49
+ initialSelectedFiles,
50
+ isFormDisabled,
51
+ isWarningDeleteOpen,
52
+ multiple,
53
+ selectedFiles,
54
+ submitEditNewFile,
55
+ submitEditExistingFile,
56
+ toggleModalWarning,
57
+ } = useModalContext();
58
+ const {
59
+ backButtonDestination,
60
+ Component,
61
+ components,
62
+ headerBreadcrumbs,
63
+ next,
64
+ prev,
65
+ withBackButton,
66
+ HeaderComponent,
67
+ } = stepper[currentStep];
68
+ const filesToUploadLength = filesToUpload.length;
69
+ const editModalRef = useRef();
70
+
71
+ const handleReplaceMedia = () => {
72
+ emitEvent('didReplaceMedia', { location: 'upload' });
73
+
74
+ editModalRef.current.click();
75
+ };
76
+
77
+ useEffect(() => {
78
+ if (currentStep === 'upload') {
79
+ // Go to the modal list view when file uploading is over
80
+
81
+ if (filesToUploadLength === 0) {
82
+ goToList();
83
+ } else {
84
+ downloadFiles();
85
+ }
86
+ }
87
+ // eslint-disable-next-line react-hooks/exhaustive-deps
88
+ }, [filesToUploadLength, currentStep]);
89
+
90
+ const addFilesToUploadList = ({ target: { value } }) => {
91
+ addFilesToUpload({ target: { value } });
92
+
93
+ goNext();
94
+ };
95
+
96
+ const goBack = (elementName = null) => {
97
+ const hasFilesToUpload = !isEmpty(filesToUpload);
98
+
99
+ // Redirect the user to the list modal from the upload one
100
+ if (elementName === 'backButton' && backButtonDestination && currentStep === 'upload') {
101
+ if (hasFilesToUpload) {
102
+ // eslint-disable-next-line no-alert
103
+ const confirm = window.confirm(
104
+ formatMessage({ id: getTrad('window.confirm.close-modal.files') })
105
+ );
106
+
107
+ if (!confirm) {
108
+ return;
109
+ }
110
+ }
111
+
112
+ goTo(backButtonDestination);
113
+ handleClearFilesToUploadAndDownload();
114
+
115
+ return;
116
+ }
117
+
118
+ if (
119
+ elementName === 'backButton' &&
120
+ backButtonDestination &&
121
+ currentStep === 'browse' &&
122
+ hasFilesToUpload
123
+ ) {
124
+ goTo(backButtonDestination);
125
+
126
+ return;
127
+ }
128
+
129
+ goTo(prev);
130
+ };
131
+
132
+ const goNext = () => {
133
+ if (next === null) {
134
+ onToggle();
135
+
136
+ return;
137
+ }
138
+
139
+ goTo(next);
140
+ };
141
+
142
+ const goToList = () => {
143
+ fetchMediaLib();
144
+ goTo('list');
145
+ };
146
+
147
+ const handleClickDeleteFile = async () => {
148
+ toggleModalWarning();
149
+ };
150
+
151
+ const handleClickDeleteFileToUpload = fileIndex => {
152
+ handleRemoveFileToUpload(fileIndex);
153
+
154
+ if (currentStep === 'edit-new') {
155
+ handleResetFileToEdit();
156
+
157
+ goNext();
158
+ }
159
+ };
160
+
161
+ const handleCloseModal = () => {
162
+ setDisplayNextButton(false);
163
+ handleClose();
164
+ };
165
+
166
+ const handleConfirmDeleteFile = () => {
167
+ setShouldDeleteFile(true);
168
+ toggleModalWarning();
169
+ };
170
+
171
+ const handleGoToAddBrowseFiles = () => {
172
+ handleCleanFilesError();
173
+
174
+ goBack();
175
+ };
176
+
177
+ const handleSubmitEditNewFile = e => {
178
+ e.preventDefault();
179
+ submitEditNewFile();
180
+ goNext();
181
+ };
182
+
183
+ const handleSubmit = e => {
184
+ e.preventDefault();
185
+ onInputMediaChange(multiple ? selectedFiles : selectedFiles[0]);
186
+ goNext();
187
+ };
188
+
189
+ const handleCloseModalWarning = async () => {
190
+ if (shouldDeleteFile) {
191
+ const { id } = fileToEdit;
192
+
193
+ try {
194
+ const requestURL = getRequestUrl(`files/${id}`);
195
+
196
+ await request(requestURL, { method: 'DELETE' });
197
+
198
+ setShouldDeleteFile(false);
199
+
200
+ // Remove file from selected files on delete and go back to the list.
201
+ handleFileSelection({ target: { name: id } });
202
+ goToList();
203
+ } catch (err) {
204
+ console.error(err);
205
+
206
+ const status = get(err, 'response.status', get(err, 'status', null));
207
+ const statusText = get(err, 'response.statusText', get(err, 'statusText', null));
208
+ const errorMessage = get(
209
+ err,
210
+ ['response', 'payload', 'message', '0', 'messages', '0', 'message'],
211
+ get(err, ['response', 'payload', 'message'], statusText)
212
+ );
213
+ strapi.notification.toggle({
214
+ type: 'warning',
215
+ message: errorMessage,
216
+ });
217
+
218
+ if (status) {
219
+ handleSetFileToEditError(errorMessage);
220
+ }
221
+ }
222
+ }
223
+ };
224
+
225
+ const handleSubmitEditExistingFile = async (
226
+ e,
227
+ shouldDuplicateMedia = false,
228
+ file = fileToEdit.file,
229
+ isSubmittingAfterCrop = false
230
+ ) => {
231
+ e.preventDefault();
232
+
233
+ submitEditExistingFile();
234
+
235
+ if (isSubmittingAfterCrop) {
236
+ emitEvent('didCropFile', {
237
+ duplicatedFile: shouldDuplicateMedia,
238
+ location: 'content-manager',
239
+ });
240
+ }
241
+
242
+ const headers = {};
243
+ const formData = new FormData();
244
+
245
+ // If the file has been cropped we need to add it to the formData
246
+ // otherwise we just don't send it
247
+ const didCropFile = file instanceof File;
248
+ const { abortController, id, fileInfo } = fileToEdit;
249
+ const requestURL = shouldDuplicateMedia ? `/${pluginId}` : `/${pluginId}?id=${id}`;
250
+
251
+ if (didCropFile) {
252
+ formData.append('files', file);
253
+ }
254
+
255
+ formData.append('fileInfo', JSON.stringify(fileInfo));
256
+
257
+ try {
258
+ const editedFile = await request(
259
+ requestURL,
260
+ {
261
+ method: 'POST',
262
+ headers,
263
+ body: formData,
264
+ signal: abortController.signal,
265
+ },
266
+ false,
267
+ false
268
+ );
269
+
270
+ handleEditExistingFile(editedFile);
271
+ goToList();
272
+ } catch (err) {
273
+ const status = get(err, 'response.status', get(err, 'status', null));
274
+ const statusText = get(err, 'response.statusText', get(err, 'statusText', null));
275
+ let errorMessage = get(
276
+ err,
277
+ ['response', 'payload', 'message', '0', 'messages', '0', 'message'],
278
+ get(err, ['response', 'payload', 'message'], statusText)
279
+ );
280
+
281
+ // TODO fix errors globally when the back-end sends readable one
282
+ if (status === 413) {
283
+ errorMessage = formatMessage({ id: 'app.utils.errors.file-too-big.message' });
284
+ }
285
+
286
+ if (status) {
287
+ handleSetFileToEditError(errorMessage);
288
+ }
289
+ }
290
+ };
291
+
292
+ const handleToggle = () => {
293
+ if (filesToUploadLength > 0) {
294
+ // eslint-disable-next-line no-alert
295
+ const confirm = window.confirm(
296
+ formatMessage({ id: getTrad('window.confirm.close-modal.files') })
297
+ );
298
+
299
+ if (!confirm) {
300
+ return;
301
+ }
302
+ }
303
+
304
+ if (
305
+ (currentStep === 'list' && !isEqual(selectedFiles, initialSelectedFiles)) ||
306
+ (currentStep === 'edit' && initialFileToEdit && !isEqual(fileToEdit, initialFileToEdit)) ||
307
+ (currentStep === 'edit' && selectedFiles.length > 0)
308
+ ) {
309
+ // eslint-disable-next-line no-alert
310
+ const confirm = window.confirm(
311
+ formatMessage({ id: getTrad('window.confirm.close-modal.file') })
312
+ );
313
+
314
+ if (!confirm) {
315
+ return;
316
+ }
317
+ }
318
+
319
+ onToggle(true);
320
+ };
321
+
322
+ const shouldDisplayNextButton = currentStep === 'browse' && displayNextButton;
323
+ const isFinishButtonDisabled = filesToUpload.some(file => file.isDownloading || file.isUploading);
324
+ const areButtonsDisabledOnEditExistingFile =
325
+ currentStep === 'edit' && fileToEdit.isUploading === true;
326
+
327
+ return (
328
+ <>
329
+ <Modal isOpen={isOpen} onToggle={handleToggle} onClosed={handleCloseModal}>
330
+ {/* header title */}
331
+ <ModalHeader
332
+ goBack={goBack}
333
+ HeaderComponent={HeaderComponent}
334
+ headerBreadcrumbs={headerBreadcrumbs}
335
+ withBackButton={withBackButton}
336
+ />
337
+ {/* body of the modal */}
338
+ {Component && (
339
+ <Component
340
+ {...allowedActions}
341
+ addFilesToUpload={addFilesToUploadList}
342
+ components={components}
343
+ filesToDownload={filesToDownload}
344
+ filesToUpload={filesToUpload}
345
+ fileToEdit={fileToEdit}
346
+ formErrors={formErrors}
347
+ isEditingUploadedFile={currentStep === 'edit'}
348
+ isFormDisabled={isFormDisabled}
349
+ noNavigation={noNavigation}
350
+ onAbortUpload={handleAbortUpload}
351
+ onChange={handleFileToEditChange}
352
+ onClickCancelUpload={handleCancelFileToUpload}
353
+ onClickDeleteFileToUpload={
354
+ currentStep === 'edit' ? handleClickDeleteFile : handleClickDeleteFileToUpload
355
+ }
356
+ onSubmitEdit={
357
+ currentStep === 'edit' ? handleSubmitEditExistingFile : handleSubmitEditNewFile
358
+ }
359
+ onClickEditNewFile={handleGoToEditNewFile}
360
+ onGoToAddBrowseFiles={handleGoToAddBrowseFiles}
361
+ onSubmitEditNewFile={handleSubmitEditNewFile}
362
+ ref={currentStep === 'edit' ? editModalRef : null}
363
+ toggleDisableForm={handleFormDisabled}
364
+ onToggle={handleToggle}
365
+ setCropResult={handleSetCropResult}
366
+ setShouldDisplayNextButton={setDisplayNextButton}
367
+ withBackButton={withBackButton}
368
+ />
369
+ )}
370
+
371
+ <ModalFooter>
372
+ <section>
373
+ <Button type="button" color="cancel" onClick={handleToggle}>
374
+ {formatMessage({ id: 'app.components.Button.cancel' })}
375
+ </Button>
376
+ {currentStep === 'upload' && (
377
+ <Button
378
+ type="button"
379
+ color="success"
380
+ onClick={handleUploadFiles}
381
+ disabled={isFinishButtonDisabled}
382
+ >
383
+ {formatMessage(
384
+ {
385
+ id: getTrad(
386
+ `modal.upload-list.footer.button.${
387
+ filesToUploadLength > 1 ? 'plural' : 'singular'
388
+ }`
389
+ ),
390
+ },
391
+ { number: filesToUploadLength }
392
+ )}
393
+ </Button>
394
+ )}
395
+ {shouldDisplayNextButton && (
396
+ <Button
397
+ type="button"
398
+ color="primary"
399
+ onClick={handleClickNextButton}
400
+ disabled={isEmpty(filesToDownload)}
401
+ >
402
+ {formatMessage({ id: getTrad('button.next') })}
403
+ </Button>
404
+ )}
405
+ {currentStep === 'edit-new' && (
406
+ <Button color="success" type="button" onClick={handleSubmitEditNewFile}>
407
+ {formatMessage({ id: 'form.button.finish' })}
408
+ </Button>
409
+ )}
410
+ {currentStep === 'edit' && (
411
+ <div style={{ margin: 'auto 0' }}>
412
+ <Button
413
+ disabled={isFormDisabled || areButtonsDisabledOnEditExistingFile}
414
+ color="primary"
415
+ onClick={handleReplaceMedia}
416
+ style={{ marginRight: 10 }}
417
+ >
418
+ {formatMessage({ id: getTrad('control-card.replace-media') })}
419
+ </Button>
420
+
421
+ <Button
422
+ disabled={isFormDisabled || areButtonsDisabledOnEditExistingFile}
423
+ color="success"
424
+ type="button"
425
+ onClick={handleSubmitEditExistingFile}
426
+ >
427
+ {formatMessage({ id: 'form.button.finish' })}
428
+ </Button>
429
+ </div>
430
+ )}
431
+ {currentStep === 'list' && (
432
+ <Button color="success" type="button" onClick={handleSubmit}>
433
+ {formatMessage({ id: 'form.button.finish' })}
434
+ </Button>
435
+ )}
436
+ </section>
437
+ </ModalFooter>
438
+ </Modal>
439
+ <PopUpWarning
440
+ onClosed={handleCloseModalWarning}
441
+ isOpen={isWarningDeleteOpen}
442
+ toggleModal={toggleModalWarning}
443
+ popUpWarningType="danger"
444
+ onConfirm={handleConfirmDeleteFile}
445
+ />
446
+ </>
447
+ );
448
+ };
449
+
450
+ InputModalStepper.defaultProps = {
451
+ allowedActions: {
452
+ canCopyLink: true,
453
+ canCreate: true,
454
+ canDownload: true,
455
+ canMain: true,
456
+ canRead: true,
457
+ canSettings: true,
458
+ canUpdate: true,
459
+ },
460
+ noNavigation: false,
461
+ onToggle: () => {},
462
+ };
463
+
464
+ InputModalStepper.propTypes = {
465
+ allowedActions: PropTypes.shape({
466
+ canCopyLink: PropTypes.bool,
467
+ canCreate: PropTypes.bool,
468
+ canDownload: PropTypes.bool,
469
+ canMain: PropTypes.bool,
470
+ canRead: PropTypes.bool,
471
+ canSettings: PropTypes.bool,
472
+ canUpdate: PropTypes.bool,
473
+ }),
474
+ isOpen: PropTypes.bool.isRequired,
475
+ noNavigation: PropTypes.bool,
476
+ onInputMediaChange: PropTypes.func.isRequired,
477
+ onToggle: PropTypes.func,
478
+ };
479
+
480
+ export default memo(InputModalStepper);
@@ -0,0 +1,48 @@
1
+ import React, { useState, useEffect, memo } from 'react';
2
+ import { useDebounce } from '@buffetjs/hooks';
3
+ import { useGlobalContext } from 'strapi-helper-plugin';
4
+
5
+ import getTrad from '../../utils/getTrad';
6
+ import useModalContext from '../../hooks/useModalContext';
7
+ import HeaderSearch from './HeaderSearch';
8
+
9
+ const Search = () => {
10
+ const [value, setValue] = useState('');
11
+ const {
12
+ allowedActions: { canRead },
13
+ setParam,
14
+ } = useModalContext();
15
+ const { formatMessage } = useGlobalContext();
16
+ const debouncedSearch = useDebounce(value, 300);
17
+
18
+ useEffect(() => {
19
+ if (canRead) {
20
+ setParam({ name: '_q', value: debouncedSearch });
21
+ }
22
+ // eslint-disable-next-line react-hooks/exhaustive-deps
23
+ }, [debouncedSearch, canRead]);
24
+
25
+ const handleSearchChange = e => {
26
+ setValue(e.target.value);
27
+ };
28
+
29
+ const handleClear = () => {
30
+ setValue('');
31
+ };
32
+
33
+ if (!canRead) {
34
+ return null;
35
+ }
36
+
37
+ return (
38
+ <HeaderSearch
39
+ onChange={handleSearchChange}
40
+ onClear={handleClear}
41
+ placeholder={formatMessage({ id: getTrad('search.placeholder') })}
42
+ name="_q"
43
+ value={value}
44
+ />
45
+ );
46
+ };
47
+
48
+ export default memo(Search);
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useUserPermissions } from 'strapi-helper-plugin';
4
+ import { DndProvider } from 'react-dnd';
5
+ import HTML5Backend from 'react-dnd-html5-backend';
6
+ import { omit } from 'lodash';
7
+ import DragLayer from '../../components/DragLayer';
8
+
9
+ import pluginPermissions from '../../permissions';
10
+ import InputModalStepper from './InputModalStepper';
11
+ import InputModalStepperProvider from '../InputModalStepperProvider';
12
+
13
+ const InputModal = ({
14
+ allowedTypes,
15
+ filesToUpload,
16
+ fileToEdit,
17
+ isOpen,
18
+ multiple,
19
+ noNavigation,
20
+ onClosed,
21
+ onInputMediaChange,
22
+ onToggle,
23
+ selectedFiles,
24
+ step,
25
+ }) => {
26
+ const singularTypes = allowedTypes.map(type => type.substring(0, type.length - 1));
27
+ const permissions = React.useMemo(() => omit(pluginPermissions, 'main'), []);
28
+ const { allowedActions, isLoading } = useUserPermissions(permissions);
29
+
30
+ if (isLoading) {
31
+ return null;
32
+ }
33
+
34
+ return (
35
+ <DndProvider backend={HTML5Backend}>
36
+ <DragLayer />
37
+ <InputModalStepperProvider
38
+ allowedActions={allowedActions}
39
+ onClosed={onClosed}
40
+ initialFilesToUpload={filesToUpload}
41
+ initialFileToEdit={fileToEdit}
42
+ isOpen={isOpen}
43
+ multiple={multiple}
44
+ noNavigation={noNavigation}
45
+ selectedFiles={selectedFiles}
46
+ step={step}
47
+ allowedTypes={singularTypes}
48
+ >
49
+ <InputModalStepper
50
+ allowedActions={allowedActions}
51
+ isOpen={isOpen}
52
+ noNavigation={noNavigation}
53
+ onToggle={onToggle}
54
+ onInputMediaChange={onInputMediaChange}
55
+ />
56
+ </InputModalStepperProvider>
57
+ </DndProvider>
58
+ );
59
+ };
60
+
61
+ InputModal.defaultProps = {
62
+ allowedTypes: [],
63
+ filesToUpload: null,
64
+ fileToEdit: null,
65
+ noNavigation: false,
66
+ onInputMediaChange: () => {},
67
+ onToggle: () => {},
68
+ selectedFiles: [],
69
+ step: 'list',
70
+ };
71
+
72
+ InputModal.propTypes = {
73
+ allowedTypes: PropTypes.arrayOf(PropTypes.string),
74
+ filesToUpload: PropTypes.object,
75
+ fileToEdit: PropTypes.object,
76
+ isOpen: PropTypes.bool.isRequired,
77
+ multiple: PropTypes.bool.isRequired,
78
+ noNavigation: PropTypes.bool,
79
+ onClosed: PropTypes.func.isRequired,
80
+ onInputMediaChange: PropTypes.func,
81
+ onToggle: PropTypes.func,
82
+ selectedFiles: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
83
+ step: PropTypes.string,
84
+ };
85
+
86
+ export default InputModal;
@@ -0,0 +1,52 @@
1
+ import CheckControl from '../../components/CheckControl';
2
+ import EditForm from '../../components/EditForm';
3
+ import getTrad from '../../utils/getTrad';
4
+ import ListModal from '../../components/ListModal';
5
+ import Search from './Search';
6
+ import UploadForm from '../../components/UploadForm';
7
+ import UploadList from '../../components/UploadList';
8
+
9
+ const stepper = {
10
+ list: {
11
+ Component: ListModal,
12
+ HeaderComponent: Search,
13
+ prev: null,
14
+ next: null,
15
+ },
16
+ browse: {
17
+ Component: UploadForm,
18
+ headerBreadcrumbs: [getTrad('modal.header.browse')],
19
+ prev: 'list',
20
+ next: 'upload',
21
+ withBackButton: true,
22
+ backButtonDestination: 'upload',
23
+ },
24
+ upload: {
25
+ Component: UploadList,
26
+ headerBreadcrumbs: [getTrad('modal.header.select-files')],
27
+ next: null,
28
+ prev: 'browse',
29
+ withBackButton: true,
30
+ // Exception in order to not update the entire code
31
+ backButtonDestination: 'list',
32
+ },
33
+ 'edit-new': {
34
+ Component: EditForm,
35
+ headerBreadcrumbs: [getTrad('modal.header.file-detail')],
36
+ next: 'upload',
37
+ prev: 'upload',
38
+ withBackButton: true,
39
+ },
40
+ edit: {
41
+ Component: EditForm,
42
+ components: {
43
+ CheckControl,
44
+ },
45
+ headerBreadcrumbs: [getTrad('modal.header.select-files'), getTrad('modal.header.file-detail')],
46
+ next: null,
47
+ prev: 'list',
48
+ withBackButton: true,
49
+ },
50
+ };
51
+
52
+ export default stepper;