@strapi/upload 5.26.0 → 5.28.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 (146) hide show
  1. package/dist/admin/ai/components/AIAssetCard.js +589 -0
  2. package/dist/admin/ai/components/AIAssetCard.js.map +1 -0
  3. package/dist/admin/ai/components/AIAssetCard.mjs +567 -0
  4. package/dist/admin/ai/components/AIAssetCard.mjs.map +1 -0
  5. package/dist/admin/ai/components/AIUploadModal.js +363 -0
  6. package/dist/admin/ai/components/AIUploadModal.js.map +1 -0
  7. package/dist/admin/ai/components/AIUploadModal.mjs +341 -0
  8. package/dist/admin/ai/components/AIUploadModal.mjs.map +1 -0
  9. package/dist/admin/components/AssetDialog/AssetDialog.js +1 -1
  10. package/dist/admin/components/AssetDialog/AssetDialog.js.map +1 -1
  11. package/dist/admin/components/AssetDialog/AssetDialog.mjs +1 -1
  12. package/dist/admin/components/AssetDialog/AssetDialog.mjs.map +1 -1
  13. package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.js +3 -3
  14. package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.js.map +1 -1
  15. package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.mjs +4 -4
  16. package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.mjs.map +1 -1
  17. package/dist/admin/components/EditAssetDialog/EditAssetContent.js +5 -5
  18. package/dist/admin/components/EditAssetDialog/EditAssetContent.js.map +1 -1
  19. package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs +5 -5
  20. package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs.map +1 -1
  21. package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.js +2 -1
  22. package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.js.map +1 -1
  23. package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.mjs +2 -1
  24. package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.mjs.map +1 -1
  25. package/dist/admin/components/SelectTree/utils/flattenTree.js +11 -6
  26. package/dist/admin/components/SelectTree/utils/flattenTree.js.map +1 -1
  27. package/dist/admin/components/SelectTree/utils/flattenTree.mjs +11 -6
  28. package/dist/admin/components/SelectTree/utils/flattenTree.mjs.map +1 -1
  29. package/dist/admin/hooks/useAiAvailability.js +22 -0
  30. package/dist/admin/hooks/useAiAvailability.js.map +1 -0
  31. package/dist/admin/hooks/useAiAvailability.mjs +20 -0
  32. package/dist/admin/hooks/useAiAvailability.mjs.map +1 -0
  33. package/dist/admin/hooks/useBulkEdit.js +66 -0
  34. package/dist/admin/hooks/useBulkEdit.js.map +1 -0
  35. package/dist/admin/hooks/useBulkEdit.mjs +64 -0
  36. package/dist/admin/hooks/useBulkEdit.mjs.map +1 -0
  37. package/dist/admin/hooks/useSettings.js +22 -0
  38. package/dist/admin/hooks/useSettings.js.map +1 -0
  39. package/dist/admin/hooks/useSettings.mjs +20 -0
  40. package/dist/admin/hooks/useSettings.mjs.map +1 -0
  41. package/dist/admin/hooks/useUpload.js +25 -14
  42. package/dist/admin/hooks/useUpload.js.map +1 -1
  43. package/dist/admin/hooks/useUpload.mjs +25 -14
  44. package/dist/admin/hooks/useUpload.mjs.map +1 -1
  45. package/dist/admin/package.json.js +5 -5
  46. package/dist/admin/package.json.mjs +5 -5
  47. package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.js +0 -1
  48. package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.js.map +1 -1
  49. package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.mjs +0 -1
  50. package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.mjs.map +1 -1
  51. package/dist/admin/pages/App/MediaLibrary/MediaLibrary.js +19 -5
  52. package/dist/admin/pages/App/MediaLibrary/MediaLibrary.js.map +1 -1
  53. package/dist/admin/pages/App/MediaLibrary/MediaLibrary.mjs +19 -5
  54. package/dist/admin/pages/App/MediaLibrary/MediaLibrary.mjs.map +1 -1
  55. package/dist/admin/pages/SettingsPage/SettingsPage.js +222 -144
  56. package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
  57. package/dist/admin/pages/SettingsPage/SettingsPage.mjs +225 -147
  58. package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
  59. package/dist/admin/pages/SettingsPage/reducer.js +9 -10
  60. package/dist/admin/pages/SettingsPage/reducer.js.map +1 -1
  61. package/dist/admin/pages/SettingsPage/reducer.mjs +9 -10
  62. package/dist/admin/pages/SettingsPage/reducer.mjs.map +1 -1
  63. package/dist/admin/src/ai/components/AIAssetCard.d.ts +13 -0
  64. package/dist/admin/src/ai/components/AIUploadModal.d.ts +55 -0
  65. package/dist/admin/src/components/EditAssetDialog/EditAssetContent.d.ts +3 -1
  66. package/dist/admin/src/components/SelectTree/utils/flattenTree.d.ts +3 -1
  67. package/dist/admin/src/hooks/useAiAvailability.d.ts +4 -0
  68. package/dist/admin/src/hooks/useBulkEdit.d.ts +91 -0
  69. package/dist/admin/src/hooks/useSettings.d.ts +7 -0
  70. package/dist/admin/src/hooks/useUpload.d.ts +1 -1
  71. package/dist/admin/src/pages/SettingsPage/reducer.d.ts +3 -12
  72. package/dist/admin/translations/en.json.js +7 -1
  73. package/dist/admin/translations/en.json.js.map +1 -1
  74. package/dist/admin/translations/en.json.mjs +7 -1
  75. package/dist/admin/translations/en.json.mjs.map +1 -1
  76. package/dist/admin/utils/getFolderParents.js +2 -1
  77. package/dist/admin/utils/getFolderParents.js.map +1 -1
  78. package/dist/admin/utils/getFolderParents.mjs +2 -1
  79. package/dist/admin/utils/getFolderParents.mjs.map +1 -1
  80. package/dist/server/bootstrap.js +2 -1
  81. package/dist/server/bootstrap.js.map +1 -1
  82. package/dist/server/bootstrap.mjs +2 -1
  83. package/dist/server/bootstrap.mjs.map +1 -1
  84. package/dist/server/controllers/admin-upload.js +57 -2
  85. package/dist/server/controllers/admin-upload.js.map +1 -1
  86. package/dist/server/controllers/admin-upload.mjs +59 -4
  87. package/dist/server/controllers/admin-upload.mjs.map +1 -1
  88. package/dist/server/controllers/content-api.js +3 -1
  89. package/dist/server/controllers/content-api.js.map +1 -1
  90. package/dist/server/controllers/content-api.mjs +3 -1
  91. package/dist/server/controllers/content-api.mjs.map +1 -1
  92. package/dist/server/controllers/validation/admin/settings.js +2 -1
  93. package/dist/server/controllers/validation/admin/settings.js.map +1 -1
  94. package/dist/server/controllers/validation/admin/settings.mjs +2 -1
  95. package/dist/server/controllers/validation/admin/settings.mjs.map +1 -1
  96. package/dist/server/controllers/validation/admin/upload.js +8 -0
  97. package/dist/server/controllers/validation/admin/upload.js.map +1 -1
  98. package/dist/server/controllers/validation/admin/upload.mjs +8 -1
  99. package/dist/server/controllers/validation/admin/upload.mjs.map +1 -1
  100. package/dist/server/routes/admin.js +18 -0
  101. package/dist/server/routes/admin.js.map +1 -1
  102. package/dist/server/routes/admin.mjs +18 -0
  103. package/dist/server/routes/admin.mjs.map +1 -1
  104. package/dist/server/services/ai-metadata.js +97 -0
  105. package/dist/server/services/ai-metadata.js.map +1 -0
  106. package/dist/server/services/ai-metadata.mjs +95 -0
  107. package/dist/server/services/ai-metadata.mjs.map +1 -0
  108. package/dist/server/services/index.js +3 -1
  109. package/dist/server/services/index.js.map +1 -1
  110. package/dist/server/services/index.mjs +3 -1
  111. package/dist/server/services/index.mjs.map +1 -1
  112. package/dist/server/services/upload.js.map +1 -1
  113. package/dist/server/services/upload.mjs.map +1 -1
  114. package/dist/server/services/weekly-metrics.js +5 -1
  115. package/dist/server/services/weekly-metrics.js.map +1 -1
  116. package/dist/server/services/weekly-metrics.mjs +5 -1
  117. package/dist/server/services/weekly-metrics.mjs.map +1 -1
  118. package/dist/server/src/bootstrap.d.ts.map +1 -1
  119. package/dist/server/src/controllers/admin-upload.d.ts +1 -0
  120. package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
  121. package/dist/server/src/controllers/index.d.ts +1 -0
  122. package/dist/server/src/controllers/index.d.ts.map +1 -1
  123. package/dist/server/src/controllers/validation/admin/settings.d.ts +3 -0
  124. package/dist/server/src/controllers/validation/admin/settings.d.ts.map +1 -1
  125. package/dist/server/src/controllers/validation/admin/upload.d.ts +42 -0
  126. package/dist/server/src/controllers/validation/admin/upload.d.ts.map +1 -1
  127. package/dist/server/src/index.d.ts +14 -1
  128. package/dist/server/src/index.d.ts.map +1 -1
  129. package/dist/server/src/routes/admin.d.ts.map +1 -1
  130. package/dist/server/src/services/ai-metadata.d.ts +13 -0
  131. package/dist/server/src/services/ai-metadata.d.ts.map +1 -0
  132. package/dist/server/src/services/index.d.ts +13 -1
  133. package/dist/server/src/services/index.d.ts.map +1 -1
  134. package/dist/server/src/services/upload.d.ts +2 -1
  135. package/dist/server/src/services/upload.d.ts.map +1 -1
  136. package/dist/server/src/services/weekly-metrics.d.ts +1 -0
  137. package/dist/server/src/services/weekly-metrics.d.ts.map +1 -1
  138. package/dist/server/src/types.d.ts +1 -0
  139. package/dist/server/src/types.d.ts.map +1 -1
  140. package/dist/server/src/utils/index.d.ts +2 -0
  141. package/dist/server/src/utils/index.d.ts.map +1 -1
  142. package/dist/server/utils/index.js.map +1 -1
  143. package/dist/server/utils/index.mjs.map +1 -1
  144. package/dist/shared/contracts/files.d.ts +22 -0
  145. package/dist/shared/contracts/settings.d.ts +2 -0
  146. package/package.json +5 -5
@@ -0,0 +1,363 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var strapiAdmin = require('@strapi/admin/strapi-admin');
6
+ var designSystem = require('@strapi/design-system');
7
+ var immer = require('immer');
8
+ var reactIntl = require('react-intl');
9
+ var styledComponents = require('styled-components');
10
+ var AddAssetStep = require('../../components/UploadAssetDialog/AddAssetStep/AddAssetStep.js');
11
+ var useBulkEdit = require('../../hooks/useBulkEdit.js');
12
+ var useUpload = require('../../hooks/useUpload.js');
13
+ require('byte-size');
14
+ require('date-fns');
15
+ var getTrad = require('../../utils/getTrad.js');
16
+ require('qs');
17
+ require('../../constants.js');
18
+ require('../../utils/urlYupSchema.js');
19
+ var AIAssetCard = require('./AIAssetCard.js');
20
+
21
+ function _interopNamespaceDefault(e) {
22
+ var n = Object.create(null);
23
+ if (e) {
24
+ Object.keys(e).forEach(function (k) {
25
+ if (k !== 'default') {
26
+ var d = Object.getOwnPropertyDescriptor(e, k);
27
+ Object.defineProperty(n, k, d.get ? d : {
28
+ enumerable: true,
29
+ get: function () { return e[k]; }
30
+ });
31
+ }
32
+ });
33
+ }
34
+ n.default = e;
35
+ return Object.freeze(n);
36
+ }
37
+
38
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
39
+
40
+ /* -------------------------------------------------------------------------------------------------
41
+ * ModalBody
42
+ * -----------------------------------------------------------------------------------------------*/ const StyledModalBody = styledComponents.styled(designSystem.Modal.Body)`
43
+ padding: 0;
44
+ display: flex;
45
+ justify-content: center;
46
+
47
+ [data-radix-scroll-area-viewport] {
48
+ padding-top: ${({ theme })=>theme.spaces[6]};
49
+ padding-bottom: ${({ theme })=>theme.spaces[6]};
50
+ padding-left: ${({ theme })=>theme.spaces[7]};
51
+ padding-right: ${({ theme })=>theme.spaces[7]};
52
+ }
53
+ `;
54
+ const StyledAlert = styledComponents.styled(designSystem.Alert)`
55
+ & > button {
56
+ display: none;
57
+ }
58
+ `;
59
+ const ModalContent = ({ onClose })=>{
60
+ const { formatMessage } = reactIntl.useIntl();
61
+ const state = useAIUploadModalContext('ModalContent', (s)=>s.state);
62
+ const dispatch = useAIUploadModalContext('ModalContent', (s)=>s.dispatch);
63
+ const folderId = useAIUploadModalContext('ModalContent', (s)=>s.folderId);
64
+ const { upload } = useUpload.useUpload();
65
+ const { edit, isLoading: isSaving } = useBulkEdit.useBulkEdit();
66
+ const [isUploading, setIsUploading] = React__namespace.useState(false);
67
+ const [uploadError, setUploadError] = React__namespace.useState(null);
68
+ const { trackUsage } = strapiAdmin.useTracking();
69
+ const handleCaptionChange = (assetId, caption)=>{
70
+ dispatch({
71
+ type: 'set_uploaded_asset_caption',
72
+ payload: {
73
+ id: assetId,
74
+ caption
75
+ }
76
+ });
77
+ };
78
+ const handleAltTextChange = (assetId, altText)=>{
79
+ dispatch({
80
+ type: 'set_uploaded_asset_alt_text',
81
+ payload: {
82
+ id: assetId,
83
+ altText
84
+ }
85
+ });
86
+ };
87
+ const resetState = ()=>{
88
+ dispatch({
89
+ type: 'set_uploaded_assets',
90
+ payload: []
91
+ });
92
+ };
93
+ const handleFinish = async ()=>{
94
+ if (state.hasUnsavedChanges) {
95
+ const assetsToUpdate = state.uploadedAssets.filter((asset)=>(asset.wasCaptionChanged || asset.wasAltTextChanged) && asset.file.id);
96
+ if (assetsToUpdate.length > 0) {
97
+ if (assetsToUpdate.some((asset)=>asset.wasCaptionChanged)) {
98
+ trackUsage('didEditAICaption');
99
+ }
100
+ if (assetsToUpdate.some((asset)=>asset.wasAltTextChanged)) {
101
+ trackUsage('didEditAIAlternativeText');
102
+ }
103
+ // Update assets
104
+ const updates = assetsToUpdate.map((asset)=>({
105
+ id: asset.file.id,
106
+ fileInfo: {
107
+ name: asset.file.name,
108
+ alternativeText: asset.file.alternativeText ?? null,
109
+ caption: asset.file.caption ?? null,
110
+ folder: typeof asset.file.folder === 'object' && asset.file.folder !== null ? asset.file.folder.id : asset.file.folder
111
+ }
112
+ }));
113
+ try {
114
+ await edit(updates);
115
+ dispatch({
116
+ type: 'clear_unsaved_changes'
117
+ });
118
+ } catch (err) {
119
+ console.error('Failed to save asset changes:', err);
120
+ return; // Don't close modal on error
121
+ }
122
+ }
123
+ }
124
+ resetState();
125
+ onClose();
126
+ };
127
+ const handleCancel = ()=>{
128
+ resetState();
129
+ onClose();
130
+ };
131
+ const handleUpload = async (assets)=>{
132
+ dispatch({
133
+ type: 'set_assets_to_upload_length',
134
+ payload: assets.length
135
+ });
136
+ setUploadError(null);
137
+ setIsUploading(true);
138
+ try {
139
+ const assetsForUpload = assets.map((asset)=>({
140
+ ...asset,
141
+ id: asset.id ? Number(asset.id) : undefined
142
+ }));
143
+ const uploadedFiles = await upload(assetsForUpload, folderId);
144
+ const filesWithFolder = uploadedFiles.map((file)=>({
145
+ ...file,
146
+ // The upload API doesn't populate the folder relation, so we add it manually
147
+ folder: folderId || file.folder
148
+ }));
149
+ dispatch({
150
+ type: 'set_uploaded_assets',
151
+ payload: filesWithFolder
152
+ });
153
+ } catch (error) {
154
+ console.error('Upload failed:', error);
155
+ setUploadError(error instanceof Error ? error : new Error('Upload failed'));
156
+ } finally{
157
+ setIsUploading(false);
158
+ }
159
+ };
160
+ if (state.assetsToUploadLength === 0) {
161
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Content, {
162
+ children: /*#__PURE__*/ jsxRuntime.jsx(AddAssetStep.AddAssetStep, {
163
+ onClose: onClose,
164
+ onAddAsset: handleUpload
165
+ })
166
+ });
167
+ }
168
+ if (isUploading || state.assetsToUploadLength > 0 && state.uploadedAssets.length === 0 && !uploadError) {
169
+ return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Content, {
170
+ children: [
171
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
172
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Title, {
173
+ children: formatMessage({
174
+ id: getTrad.getTrad('ai.modal.uploading.title'),
175
+ defaultMessage: 'Uploading and processing with AI...'
176
+ })
177
+ })
178
+ }),
179
+ /*#__PURE__*/ jsxRuntime.jsx(StyledModalBody, {
180
+ children: /*#__PURE__*/ jsxRuntime.jsx(AIAssetCard.AIAssetCardSkeletons, {
181
+ count: state.assetsToUploadLength
182
+ })
183
+ })
184
+ ]
185
+ });
186
+ }
187
+ const title = formatMessage({
188
+ id: getTrad.getTrad('ai.modal.title'),
189
+ defaultMessage: '{count, plural, one {# asset uploaded} other {# assets uploaded}}, review AI generated metadata'
190
+ }, {
191
+ count: state.uploadedAssets.length
192
+ });
193
+ if (uploadError) {
194
+ return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Content, {
195
+ children: [
196
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
197
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Title, {
198
+ children: title
199
+ })
200
+ }),
201
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Body, {
202
+ children: /*#__PURE__*/ jsxRuntime.jsx(StyledAlert, {
203
+ closeLabel: "",
204
+ variant: "danger",
205
+ children: formatMessage({
206
+ id: getTrad.getTrad('ai.modal.error'),
207
+ defaultMessage: 'Could not generate AI metadata for the uploaded files.'
208
+ })
209
+ })
210
+ }),
211
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Footer, {
212
+ children: [
213
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
214
+ onClick: handleCancel,
215
+ variant: "tertiary",
216
+ children: formatMessage({
217
+ id: 'cancel',
218
+ defaultMessage: 'Cancel'
219
+ })
220
+ }),
221
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
222
+ onClick: handleFinish,
223
+ loading: isSaving,
224
+ children: formatMessage({
225
+ id: 'global.finish',
226
+ defaultMessage: 'Finish'
227
+ })
228
+ })
229
+ ]
230
+ })
231
+ ]
232
+ });
233
+ }
234
+ return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Content, {
235
+ children: [
236
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
237
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Title, {
238
+ children: title
239
+ })
240
+ }),
241
+ /*#__PURE__*/ jsxRuntime.jsx(StyledModalBody, {
242
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
243
+ gap: 6,
244
+ direction: "column",
245
+ alignItems: "stretch",
246
+ children: state.uploadedAssets.map(({ file: asset, wasCaptionChanged, wasAltTextChanged })=>/*#__PURE__*/ jsxRuntime.jsx(AIAssetCard.AIAssetCard, {
247
+ asset: asset,
248
+ onCaptionChange: (caption)=>asset.id && handleCaptionChange(asset.id, caption),
249
+ onAltTextChange: (altText)=>asset.id && handleAltTextChange(asset.id, altText),
250
+ wasCaptionChanged: wasCaptionChanged,
251
+ wasAltTextChanged: wasAltTextChanged
252
+ }, asset.id))
253
+ })
254
+ }),
255
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Footer, {
256
+ children: [
257
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
258
+ onClick: handleCancel,
259
+ variant: "tertiary",
260
+ children: formatMessage({
261
+ id: 'cancel',
262
+ defaultMessage: 'Cancel'
263
+ })
264
+ }),
265
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
266
+ onClick: handleFinish,
267
+ loading: isSaving,
268
+ children: formatMessage({
269
+ id: 'global.finish',
270
+ defaultMessage: 'Finish'
271
+ })
272
+ })
273
+ ]
274
+ })
275
+ ]
276
+ });
277
+ };
278
+ const [AIUploadModalContext, useAIUploadModalContext] = strapiAdmin.createContext('AIUploadModalContext');
279
+ const reducer = (state, action)=>{
280
+ return immer.produce(state, (draft)=>{
281
+ if (action.type === 'set_uploaded_assets') {
282
+ draft.uploadedAssets = action.payload.map((file)=>({
283
+ file,
284
+ wasCaptionChanged: false,
285
+ wasAltTextChanged: false
286
+ }));
287
+ draft.hasUnsavedChanges = false;
288
+ }
289
+ if (action.type === 'set_assets_to_upload_length') {
290
+ draft.assetsToUploadLength = action.payload;
291
+ }
292
+ if (action.type === 'set_uploaded_asset_caption') {
293
+ const asset = draft.uploadedAssets.find((a)=>a.file.id === action.payload.id);
294
+ if (asset && asset.file.caption !== action.payload.caption) {
295
+ asset.file.caption = action.payload.caption;
296
+ asset.wasCaptionChanged = true;
297
+ draft.hasUnsavedChanges = true;
298
+ }
299
+ }
300
+ if (action.type === 'set_uploaded_asset_alt_text') {
301
+ const asset = draft.uploadedAssets.find((a)=>a.file.id === action.payload.id);
302
+ if (asset && asset.file.alternativeText !== action.payload.altText) {
303
+ asset.file.alternativeText = action.payload.altText;
304
+ asset.wasAltTextChanged = true;
305
+ draft.hasUnsavedChanges = true;
306
+ }
307
+ }
308
+ if (action.type === 'remove_uploaded_asset') {
309
+ draft.uploadedAssets = draft.uploadedAssets.filter((a)=>a.file.id !== action.payload.id);
310
+ }
311
+ if (action.type === 'edit_uploaded_asset') {
312
+ const assetIndex = draft.uploadedAssets.findIndex((a)=>a.file.id === action.payload.editedAsset.id);
313
+ if (assetIndex !== -1) {
314
+ draft.uploadedAssets[assetIndex] = {
315
+ file: action.payload.editedAsset,
316
+ wasCaptionChanged: draft.uploadedAssets[assetIndex].wasCaptionChanged,
317
+ wasAltTextChanged: draft.uploadedAssets[assetIndex].wasAltTextChanged
318
+ };
319
+ }
320
+ }
321
+ if (action.type === 'clear_unsaved_changes') {
322
+ draft.hasUnsavedChanges = false;
323
+ draft.uploadedAssets.forEach((asset)=>{
324
+ asset.wasCaptionChanged = false;
325
+ asset.wasAltTextChanged = false;
326
+ });
327
+ }
328
+ });
329
+ };
330
+ const AIUploadModal = ({ open, onClose, folderId = null })=>{
331
+ const [state, dispatch] = React__namespace.useReducer(reducer, {
332
+ uploadedAssets: [],
333
+ assetsToUploadLength: 0,
334
+ hasUnsavedChanges: false
335
+ });
336
+ const handleClose = React__namespace.useCallback(()=>{
337
+ // Reset state when modal closes
338
+ dispatch({
339
+ type: 'set_uploaded_assets',
340
+ payload: []
341
+ });
342
+ onClose();
343
+ }, [
344
+ onClose
345
+ ]);
346
+ return /*#__PURE__*/ jsxRuntime.jsx(AIUploadModalContext, {
347
+ state: state,
348
+ dispatch: dispatch,
349
+ folderId: folderId,
350
+ onClose: handleClose,
351
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Root, {
352
+ open: open,
353
+ onOpenChange: handleClose,
354
+ children: /*#__PURE__*/ jsxRuntime.jsx(ModalContent, {
355
+ onClose: handleClose
356
+ })
357
+ })
358
+ });
359
+ };
360
+
361
+ exports.AIUploadModal = AIUploadModal;
362
+ exports.useAIUploadModalContext = useAIUploadModalContext;
363
+ //# sourceMappingURL=AIUploadModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIUploadModal.js","sources":["../../../../admin/src/ai/components/AIUploadModal.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { createContext, useTracking } from '@strapi/admin/strapi-admin';\nimport { Alert, Button, Flex, Modal } from '@strapi/design-system';\nimport { produce } from 'immer';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport {\n AddAssetStep,\n FileWithRawFile,\n} from '../../components/UploadAssetDialog/AddAssetStep/AddAssetStep';\nimport { AssetType } from '../../constants';\nimport { useBulkEdit } from '../../hooks/useBulkEdit';\nimport { useUpload } from '../../hooks/useUpload';\nimport { getTrad, typeFromMime } from '../../utils';\n\nimport { AIAssetCard, AIAssetCardSkeletons } from './AIAssetCard';\n\nimport type { File } from '../../../../shared/contracts/files';\n\n/* -------------------------------------------------------------------------------------------------\n * ModalBody\n * -----------------------------------------------------------------------------------------------*/\n\nconst StyledModalBody = styled(Modal.Body)`\n padding: 0;\n display: flex;\n justify-content: center;\n\n [data-radix-scroll-area-viewport] {\n padding-top: ${({ theme }) => theme.spaces[6]};\n padding-bottom: ${({ theme }) => theme.spaces[6]};\n padding-left: ${({ theme }) => theme.spaces[7]};\n padding-right: ${({ theme }) => theme.spaces[7]};\n }\n`;\n\nconst StyledAlert = styled(Alert)`\n & > button {\n display: none;\n }\n`;\n\nconst ModalContent = ({ onClose }: Pick<AIUploadModalProps, 'onClose'>) => {\n const { formatMessage } = useIntl();\n const state = useAIUploadModalContext('ModalContent', (s) => s.state);\n const dispatch = useAIUploadModalContext('ModalContent', (s) => s.dispatch);\n const folderId = useAIUploadModalContext('ModalContent', (s) => s.folderId);\n const { upload } = useUpload();\n const { edit, isLoading: isSaving } = useBulkEdit();\n const [isUploading, setIsUploading] = React.useState(false);\n const [uploadError, setUploadError] = React.useState<Error | null>(null);\n const { trackUsage } = useTracking();\n\n const handleCaptionChange = (assetId: number, caption: string) => {\n dispatch({\n type: 'set_uploaded_asset_caption',\n payload: { id: assetId, caption },\n });\n };\n\n const handleAltTextChange = (assetId: number, altText: string) => {\n dispatch({\n type: 'set_uploaded_asset_alt_text',\n payload: { id: assetId, altText },\n });\n };\n\n const resetState = () => {\n dispatch({ type: 'set_uploaded_assets', payload: [] });\n };\n\n const handleFinish = async () => {\n if (state.hasUnsavedChanges) {\n const assetsToUpdate = state.uploadedAssets.filter(\n (asset) => (asset.wasCaptionChanged || asset.wasAltTextChanged) && asset.file.id\n );\n\n if (assetsToUpdate.length > 0) {\n if (assetsToUpdate.some((asset) => asset.wasCaptionChanged)) {\n trackUsage('didEditAICaption');\n }\n\n if (assetsToUpdate.some((asset) => asset.wasAltTextChanged)) {\n trackUsage('didEditAIAlternativeText');\n }\n\n // Update assets\n const updates = assetsToUpdate.map((asset) => ({\n id: asset.file.id!,\n fileInfo: {\n name: asset.file.name,\n alternativeText: asset.file.alternativeText ?? null,\n caption: asset.file.caption ?? null,\n folder:\n typeof asset.file.folder === 'object' && asset.file.folder !== null\n ? // @ts-expect-error types are wrong\n asset.file.folder.id\n : asset.file.folder,\n },\n }));\n\n try {\n await edit(updates);\n dispatch({ type: 'clear_unsaved_changes' });\n } catch (err) {\n console.error('Failed to save asset changes:', err);\n return; // Don't close modal on error\n }\n }\n }\n\n resetState();\n onClose();\n };\n\n const handleCancel = () => {\n resetState();\n onClose();\n };\n\n const handleUpload = async (assets: FileWithRawFile[]) => {\n dispatch({ type: 'set_assets_to_upload_length', payload: assets.length });\n setUploadError(null);\n setIsUploading(true);\n\n try {\n const assetsForUpload = assets.map((asset) => ({\n ...asset,\n id: asset.id ? Number(asset.id) : undefined,\n }));\n\n const uploadedFiles = await upload(assetsForUpload, folderId);\n const filesWithFolder = uploadedFiles.map((file: File) => ({\n ...file,\n // The upload API doesn't populate the folder relation, so we add it manually\n folder: folderId || file.folder,\n }));\n dispatch({ type: 'set_uploaded_assets', payload: filesWithFolder });\n } catch (error) {\n console.error('Upload failed:', error);\n setUploadError(error instanceof Error ? error : new Error('Upload failed'));\n } finally {\n setIsUploading(false);\n }\n };\n\n if (state.assetsToUploadLength === 0) {\n return (\n <Modal.Content>\n <AddAssetStep onClose={onClose} onAddAsset={handleUpload} />\n </Modal.Content>\n );\n }\n\n if (\n isUploading ||\n (state.assetsToUploadLength > 0 && state.uploadedAssets.length === 0 && !uploadError)\n ) {\n return (\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>\n {formatMessage({\n id: getTrad('ai.modal.uploading.title'),\n defaultMessage: 'Uploading and processing with AI...',\n })}\n </Modal.Title>\n </Modal.Header>\n <StyledModalBody>\n <AIAssetCardSkeletons count={state.assetsToUploadLength} />\n </StyledModalBody>\n </Modal.Content>\n );\n }\n\n const title = formatMessage(\n {\n id: getTrad('ai.modal.title'),\n defaultMessage:\n '{count, plural, one {# asset uploaded} other {# assets uploaded}}, review AI generated metadata',\n },\n { count: state.uploadedAssets.length }\n );\n\n if (uploadError) {\n return (\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>{title}</Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <StyledAlert closeLabel=\"\" variant=\"danger\">\n {formatMessage({\n id: getTrad('ai.modal.error'),\n defaultMessage: 'Could not generate AI metadata for the uploaded files.',\n })}\n </StyledAlert>\n </Modal.Body>\n <Modal.Footer>\n <Button onClick={handleCancel} variant=\"tertiary\">\n {formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button onClick={handleFinish} loading={isSaving}>\n {formatMessage({ id: 'global.finish', defaultMessage: 'Finish' })}\n </Button>\n </Modal.Footer>\n </Modal.Content>\n );\n }\n\n return (\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>{title}</Modal.Title>\n </Modal.Header>\n\n <StyledModalBody>\n <Flex gap={6} direction=\"column\" alignItems=\"stretch\">\n {state.uploadedAssets.map(({ file: asset, wasCaptionChanged, wasAltTextChanged }) => (\n <AIAssetCard\n key={asset.id}\n asset={asset}\n onCaptionChange={(caption: string) =>\n asset.id && handleCaptionChange(asset.id, caption)\n }\n onAltTextChange={(altText: string) =>\n asset.id && handleAltTextChange(asset.id, altText)\n }\n wasCaptionChanged={wasCaptionChanged}\n wasAltTextChanged={wasAltTextChanged}\n />\n ))}\n </Flex>\n </StyledModalBody>\n\n <Modal.Footer>\n <Button onClick={handleCancel} variant=\"tertiary\">\n {formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button onClick={handleFinish} loading={isSaving}>\n {formatMessage({ id: 'global.finish', defaultMessage: 'Finish' })}\n </Button>\n </Modal.Footer>\n </Modal.Content>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * UploadModal\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AIUploadModalProps {\n open: boolean;\n onClose: () => void;\n folderId?: number | null;\n}\n\ntype State = {\n uploadedAssets: Array<{ file: File; wasCaptionChanged: boolean; wasAltTextChanged: boolean }>;\n assetsToUploadLength: number;\n hasUnsavedChanges: boolean;\n};\n\ntype Action =\n | {\n type: 'set_uploaded_assets';\n payload: File[];\n }\n | {\n type: 'set_assets_to_upload_length';\n payload: number;\n }\n | {\n type: 'set_uploaded_asset_caption';\n payload: { id: number; caption: string };\n }\n | {\n type: 'set_uploaded_asset_alt_text';\n payload: { id: number; altText: string };\n }\n | {\n type: 'remove_uploaded_asset';\n payload: { id: number };\n }\n | {\n type: 'edit_uploaded_asset';\n payload: { editedAsset: File };\n }\n | {\n type: 'clear_unsaved_changes';\n };\n\nconst [AIUploadModalContext, useAIUploadModalContext] = createContext<{\n state: State;\n dispatch: React.Dispatch<Action>;\n folderId: number | null;\n onClose: () => void;\n}>('AIUploadModalContext');\n\nconst reducer = (state: State, action: Action): State => {\n return produce(state, (draft: State) => {\n if (action.type === 'set_uploaded_assets') {\n draft.uploadedAssets = action.payload.map((file) => ({\n file,\n wasCaptionChanged: false,\n wasAltTextChanged: false,\n }));\n draft.hasUnsavedChanges = false;\n }\n\n if (action.type === 'set_assets_to_upload_length') {\n draft.assetsToUploadLength = action.payload;\n }\n\n if (action.type === 'set_uploaded_asset_caption') {\n const asset = draft.uploadedAssets.find((a) => a.file.id === action.payload.id);\n if (asset && asset.file.caption !== action.payload.caption) {\n asset.file.caption = action.payload.caption;\n asset.wasCaptionChanged = true;\n draft.hasUnsavedChanges = true;\n }\n }\n\n if (action.type === 'set_uploaded_asset_alt_text') {\n const asset = draft.uploadedAssets.find((a) => a.file.id === action.payload.id);\n if (asset && asset.file.alternativeText !== action.payload.altText) {\n asset.file.alternativeText = action.payload.altText;\n asset.wasAltTextChanged = true;\n draft.hasUnsavedChanges = true;\n }\n }\n\n if (action.type === 'remove_uploaded_asset') {\n draft.uploadedAssets = draft.uploadedAssets.filter((a) => a.file.id !== action.payload.id);\n }\n\n if (action.type === 'edit_uploaded_asset') {\n const assetIndex = draft.uploadedAssets.findIndex(\n (a) => a.file.id === action.payload.editedAsset.id\n );\n if (assetIndex !== -1) {\n draft.uploadedAssets[assetIndex] = {\n file: action.payload.editedAsset,\n wasCaptionChanged: draft.uploadedAssets[assetIndex].wasCaptionChanged,\n wasAltTextChanged: draft.uploadedAssets[assetIndex].wasAltTextChanged,\n };\n }\n }\n\n if (action.type === 'clear_unsaved_changes') {\n draft.hasUnsavedChanges = false;\n draft.uploadedAssets.forEach((asset) => {\n asset.wasCaptionChanged = false;\n asset.wasAltTextChanged = false;\n });\n }\n });\n};\n\nexport const AIUploadModal = ({ open, onClose, folderId = null }: AIUploadModalProps) => {\n const [state, dispatch] = React.useReducer(reducer, {\n uploadedAssets: [],\n assetsToUploadLength: 0,\n hasUnsavedChanges: false,\n });\n\n const handleClose = React.useCallback(() => {\n // Reset state when modal closes\n dispatch({ type: 'set_uploaded_assets', payload: [] });\n onClose();\n }, [onClose]);\n\n return (\n <AIUploadModalContext\n state={state}\n dispatch={dispatch}\n folderId={folderId}\n onClose={handleClose}\n >\n <Modal.Root open={open} onOpenChange={handleClose}>\n <ModalContent onClose={handleClose} />\n </Modal.Root>\n </AIUploadModalContext>\n );\n};\n\nexport { useAIUploadModalContext };\n"],"names":["StyledModalBody","styled","Modal","Body","theme","spaces","StyledAlert","Alert","ModalContent","onClose","formatMessage","useIntl","state","useAIUploadModalContext","s","dispatch","folderId","upload","useUpload","edit","isLoading","isSaving","useBulkEdit","isUploading","setIsUploading","React","useState","uploadError","setUploadError","trackUsage","useTracking","handleCaptionChange","assetId","caption","type","payload","id","handleAltTextChange","altText","resetState","handleFinish","hasUnsavedChanges","assetsToUpdate","uploadedAssets","filter","asset","wasCaptionChanged","wasAltTextChanged","file","length","some","updates","map","fileInfo","name","alternativeText","folder","err","console","error","handleCancel","handleUpload","assets","assetsForUpload","Number","undefined","uploadedFiles","filesWithFolder","Error","assetsToUploadLength","_jsx","Content","AddAssetStep","onAddAsset","_jsxs","Header","Title","getTrad","defaultMessage","AIAssetCardSkeletons","count","title","closeLabel","variant","Footer","Button","onClick","loading","Flex","gap","direction","alignItems","AIAssetCard","onCaptionChange","onAltTextChange","AIUploadModalContext","createContext","reducer","action","produce","draft","find","a","assetIndex","findIndex","editedAsset","forEach","AIUploadModal","open","useReducer","handleClose","useCallback","Root","onOpenChange"],"mappings":"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"}