@strapi/upload 5.35.0 → 5.36.1

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 (130) hide show
  1. package/dist/admin/future/App.js +8 -20
  2. package/dist/admin/future/App.js.map +1 -1
  3. package/dist/admin/future/App.mjs +8 -20
  4. package/dist/admin/future/App.mjs.map +1 -1
  5. package/dist/admin/future/components/UploadProgressDialog.js +494 -0
  6. package/dist/admin/future/components/UploadProgressDialog.js.map +1 -0
  7. package/dist/admin/future/components/UploadProgressDialog.mjs +473 -0
  8. package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -0
  9. package/dist/admin/future/enums.js +12 -0
  10. package/dist/admin/future/enums.js.map +1 -0
  11. package/dist/admin/future/enums.mjs +10 -0
  12. package/dist/admin/future/enums.mjs.map +1 -0
  13. package/dist/admin/future/pages/Assets/AssetsPage.js +311 -0
  14. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -0
  15. package/dist/admin/future/pages/Assets/AssetsPage.mjs +290 -0
  16. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -0
  17. package/dist/admin/future/pages/Assets/components/AssetsGrid.js +164 -0
  18. package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -0
  19. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +162 -0
  20. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -0
  21. package/dist/admin/future/pages/Assets/components/AssetsTable.js +198 -0
  22. package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -0
  23. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +196 -0
  24. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -0
  25. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.js +127 -0
  26. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.js.map +1 -0
  27. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.mjs +105 -0
  28. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.mjs.map +1 -0
  29. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js +107 -0
  30. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js.map +1 -0
  31. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs +104 -0
  32. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs.map +1 -0
  33. package/dist/admin/future/pages/Assets/constants.js +54 -0
  34. package/dist/admin/future/pages/Assets/constants.js.map +1 -0
  35. package/dist/admin/future/pages/Assets/constants.mjs +50 -0
  36. package/dist/admin/future/pages/Assets/constants.mjs.map +1 -0
  37. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +77 -0
  38. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -0
  39. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +74 -0
  40. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -0
  41. package/dist/admin/future/services/api.js +419 -9
  42. package/dist/admin/future/services/api.js.map +1 -1
  43. package/dist/admin/future/services/api.mjs +417 -9
  44. package/dist/admin/future/services/api.mjs.map +1 -1
  45. package/dist/admin/future/services/assets.js +37 -0
  46. package/dist/admin/future/services/assets.js.map +1 -0
  47. package/dist/admin/future/services/assets.mjs +35 -0
  48. package/dist/admin/future/services/assets.mjs.map +1 -0
  49. package/dist/admin/future/store/hooks.js +10 -0
  50. package/dist/admin/future/store/hooks.js.map +1 -0
  51. package/dist/admin/future/store/hooks.mjs +7 -0
  52. package/dist/admin/future/store/hooks.mjs.map +1 -0
  53. package/dist/admin/future/store/uploadProgress.js +156 -0
  54. package/dist/admin/future/store/uploadProgress.js.map +1 -0
  55. package/dist/admin/future/store/uploadProgress.mjs +143 -0
  56. package/dist/admin/future/store/uploadProgress.mjs.map +1 -0
  57. package/dist/admin/future/utils/files.js +23 -0
  58. package/dist/admin/future/utils/files.js.map +1 -0
  59. package/dist/admin/future/utils/files.mjs +19 -0
  60. package/dist/admin/future/utils/files.mjs.map +1 -0
  61. package/dist/admin/future/utils/getAssetIcon.js +28 -0
  62. package/dist/admin/future/utils/getAssetIcon.js.map +1 -0
  63. package/dist/admin/future/utils/getAssetIcon.mjs +26 -0
  64. package/dist/admin/future/utils/getAssetIcon.mjs.map +1 -0
  65. package/dist/admin/index.js +11 -0
  66. package/dist/admin/index.js.map +1 -1
  67. package/dist/admin/index.mjs +11 -0
  68. package/dist/admin/index.mjs.map +1 -1
  69. package/dist/admin/package.json.js +11 -9
  70. package/dist/admin/package.json.js.map +1 -1
  71. package/dist/admin/package.json.mjs +11 -9
  72. package/dist/admin/package.json.mjs.map +1 -1
  73. package/dist/admin/src/future/components/UploadProgressDialog.d.ts +1 -0
  74. package/dist/admin/src/future/enums.d.ts +6 -0
  75. package/dist/admin/src/future/pages/Assets/AssetsPage.d.ts +1 -0
  76. package/dist/admin/src/future/pages/Assets/components/AssetsGrid.d.ts +6 -0
  77. package/dist/admin/src/future/pages/Assets/components/AssetsTable.d.ts +6 -0
  78. package/dist/admin/src/future/pages/Assets/components/DropZone/UploadDropZone.d.ts +9 -0
  79. package/dist/admin/src/future/pages/Assets/components/DropZone/UploadDropZoneContext.d.ts +11 -0
  80. package/dist/admin/src/future/pages/Assets/constants.d.ts +17 -0
  81. package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +17 -0
  82. package/dist/admin/src/future/services/api.d.ts +21 -3
  83. package/dist/admin/src/future/services/assets.d.ts +13 -0
  84. package/dist/admin/src/future/store/hooks.d.ts +6 -0
  85. package/dist/admin/src/future/store/uploadProgress.d.ts +46 -0
  86. package/dist/admin/src/future/utils/files.d.ts +3 -0
  87. package/dist/admin/src/future/utils/getAssetIcon.d.ts +12 -0
  88. package/dist/admin/translations/en.json.js +25 -0
  89. package/dist/admin/translations/en.json.js.map +1 -1
  90. package/dist/admin/translations/en.json.mjs +25 -0
  91. package/dist/admin/translations/en.json.mjs.map +1 -1
  92. package/dist/server/controllers/admin-upload.js +151 -2
  93. package/dist/server/controllers/admin-upload.js.map +1 -1
  94. package/dist/server/controllers/admin-upload.mjs +151 -2
  95. package/dist/server/controllers/admin-upload.mjs.map +1 -1
  96. package/dist/server/controllers/content-api.js +8 -2
  97. package/dist/server/controllers/content-api.js.map +1 -1
  98. package/dist/server/controllers/content-api.mjs +9 -3
  99. package/dist/server/controllers/content-api.mjs.map +1 -1
  100. package/dist/server/routes/admin.js +10 -0
  101. package/dist/server/routes/admin.js.map +1 -1
  102. package/dist/server/routes/admin.mjs +10 -0
  103. package/dist/server/routes/admin.mjs.map +1 -1
  104. package/dist/server/src/controllers/admin-upload.d.ts +12 -0
  105. package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
  106. package/dist/server/src/controllers/content-api.d.ts.map +1 -1
  107. package/dist/server/src/controllers/index.d.ts +1 -0
  108. package/dist/server/src/controllers/index.d.ts.map +1 -1
  109. package/dist/server/src/index.d.ts +1 -0
  110. package/dist/server/src/index.d.ts.map +1 -1
  111. package/dist/server/src/routes/admin.d.ts.map +1 -1
  112. package/dist/server/src/utils/mime-validation.d.ts +5 -0
  113. package/dist/server/src/utils/mime-validation.d.ts.map +1 -1
  114. package/dist/server/utils/mime-validation.js +7 -4
  115. package/dist/server/utils/mime-validation.js.map +1 -1
  116. package/dist/server/utils/mime-validation.mjs +7 -4
  117. package/dist/server/utils/mime-validation.mjs.map +1 -1
  118. package/dist/shared/contracts/files.d.ts +52 -0
  119. package/dist/shared/contracts/files.d.ts.map +1 -0
  120. package/package.json +11 -9
  121. package/dist/admin/future/pages/AIGenerationPage.js +0 -24
  122. package/dist/admin/future/pages/AIGenerationPage.js.map +0 -1
  123. package/dist/admin/future/pages/AIGenerationPage.mjs +0 -22
  124. package/dist/admin/future/pages/AIGenerationPage.mjs.map +0 -1
  125. package/dist/admin/future/pages/MediaLibraryPage.js +0 -119
  126. package/dist/admin/future/pages/MediaLibraryPage.js.map +0 -1
  127. package/dist/admin/future/pages/MediaLibraryPage.mjs +0 -98
  128. package/dist/admin/future/pages/MediaLibraryPage.mjs.map +0 -1
  129. package/dist/admin/src/future/pages/AIGenerationPage.d.ts +0 -1
  130. package/dist/admin/src/future/pages/MediaLibraryPage.d.ts +0 -1
@@ -0,0 +1,311 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var ToggleGroup = require('@radix-ui/react-toggle-group');
6
+ var strapiAdmin = require('@strapi/admin/strapi-admin');
7
+ var designSystem = require('@strapi/design-system');
8
+ var icons = require('@strapi/icons');
9
+ var reactIntl = require('react-intl');
10
+ var styledComponents = require('styled-components');
11
+ var api = require('../../services/api.js');
12
+ var translations = require('../../utils/translations.js');
13
+ var AssetsGrid = require('./components/AssetsGrid.js');
14
+ var AssetsTable = require('./components/AssetsTable.js');
15
+ var UploadDropZone = require('./components/DropZone/UploadDropZone.js');
16
+ var UploadDropZoneContext = require('./components/DropZone/UploadDropZoneContext.js');
17
+ var constants = require('./constants.js');
18
+ var useInfiniteAssets = require('./hooks/useInfiniteAssets.js');
19
+
20
+ function _interopNamespaceDefault(e) {
21
+ var n = Object.create(null);
22
+ if (e) {
23
+ Object.keys(e).forEach(function (k) {
24
+ if (k !== 'default') {
25
+ var d = Object.getOwnPropertyDescriptor(e, k);
26
+ Object.defineProperty(n, k, d.get ? d : {
27
+ enumerable: true,
28
+ get: function () { return e[k]; }
29
+ });
30
+ }
31
+ });
32
+ }
33
+ n.default = e;
34
+ return Object.freeze(n);
35
+ }
36
+
37
+ var ToggleGroup__namespace = /*#__PURE__*/_interopNamespaceDefault(ToggleGroup);
38
+
39
+ const INTERSECTION_OPTIONS = {
40
+ threshold: 0.1
41
+ };
42
+ const AssetsView = ({ view })=>{
43
+ const { formatMessage } = reactIntl.useIntl();
44
+ const { assets, isLoading, isFetchingMore, hasNextPage, fetchNextPage, error } = useInfiniteAssets.useInfiniteAssets();
45
+ const isGridView = view === constants.viewOptions.GRID;
46
+ const loadMoreRef = strapiAdmin.useElementOnScreen(React.useCallback((isVisible)=>{
47
+ if (isVisible && hasNextPage && !isFetchingMore) {
48
+ fetchNextPage();
49
+ }
50
+ }, [
51
+ hasNextPage,
52
+ isFetchingMore,
53
+ fetchNextPage
54
+ ]), INTERSECTION_OPTIONS);
55
+ if (isLoading) {
56
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
57
+ justifyContent: "center",
58
+ padding: 8,
59
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Loader, {
60
+ children: formatMessage({
61
+ id: 'app.loading',
62
+ defaultMessage: 'Loading...'
63
+ })
64
+ })
65
+ });
66
+ }
67
+ if (error) {
68
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
69
+ padding: 8,
70
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
71
+ textColor: "danger600",
72
+ children: formatMessage({
73
+ id: translations.getTranslationKey('list.assets.error'),
74
+ defaultMessage: 'An error occurred while fetching assets.'
75
+ })
76
+ })
77
+ });
78
+ }
79
+ return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
80
+ children: [
81
+ isGridView ? /*#__PURE__*/ jsxRuntime.jsx(AssetsGrid.AssetsGrid, {
82
+ assets: assets
83
+ }) : /*#__PURE__*/ jsxRuntime.jsx(AssetsTable.AssetsTable, {
84
+ assets: assets
85
+ }),
86
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
87
+ ref: loadMoreRef,
88
+ style: {
89
+ height: 1
90
+ }
91
+ }),
92
+ isFetchingMore && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
93
+ justifyContent: "center",
94
+ padding: 4,
95
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Loader, {
96
+ children: formatMessage({
97
+ id: translations.getTranslationKey('list.assets.loading-more'),
98
+ defaultMessage: 'Loading more assets...'
99
+ })
100
+ })
101
+ })
102
+ ]
103
+ });
104
+ };
105
+ /* -------------------------------------------------------------------------------------------------
106
+ * AssetsPage
107
+ * -----------------------------------------------------------------------------------------------*/ const StyledToggleGroup = styledComponents.styled(ToggleGroup__namespace.Root)`
108
+ display: flex;
109
+ border: 1px solid ${({ theme })=>theme.colors.neutral200};
110
+ border-radius: ${({ theme })=>theme.borderRadius};
111
+ overflow: hidden;
112
+ `;
113
+ const StyledToggleItem = styledComponents.styled(ToggleGroup__namespace.Item)`
114
+ display: flex;
115
+ align-items: center;
116
+ gap: ${({ theme })=>theme.spaces[2]};
117
+ padding: ${({ theme })=>`${theme.spaces[2]} ${theme.spaces[4]}`};
118
+ border: none;
119
+ background: ${({ theme })=>theme.colors.neutral0};
120
+ color: ${({ theme })=>theme.colors.neutral800};
121
+ cursor: pointer;
122
+ font-size: ${({ theme })=>theme.fontSizes[1]};
123
+ font-weight: ${({ theme })=>theme.fontWeights.semiBold};
124
+
125
+ &:hover {
126
+ background: ${({ theme })=>theme.colors.neutral100};
127
+ }
128
+
129
+ &[data-state='on'] {
130
+ background: ${({ theme })=>theme.colors.neutral150};
131
+ }
132
+
133
+ svg {
134
+ width: 1.6rem;
135
+ height: 1.6rem;
136
+ }
137
+ `;
138
+ const HeaderWrapper = styledComponents.styled.div`
139
+ [data-strapi-header] {
140
+ background: ${({ theme })=>theme.colors.neutral0};
141
+
142
+ h1 {
143
+ font-size: 1.8rem;
144
+ }
145
+ }
146
+ `;
147
+ const AssetsPage = ()=>{
148
+ const { formatMessage } = reactIntl.useIntl();
149
+ // View state
150
+ const [view, setView] = strapiAdmin.usePersistentState(constants.localStorageKeys.view, constants.viewOptions.GRID);
151
+ const isGridView = view === constants.viewOptions.GRID;
152
+ // Refs
153
+ const fileInputRef = React.useRef(null);
154
+ const uploadDropZoneRef = React.useRef(null);
155
+ // Upload handlers
156
+ const [uploadFilesStream] = api.useUploadFilesStreamMutation();
157
+ const uploadFilesToFolder = async (files, folderId)=>{
158
+ if (files.length === 0) return;
159
+ const formData = new FormData();
160
+ const fileInfoArray = [];
161
+ files.forEach((file)=>{
162
+ formData.append('files', file);
163
+ fileInfoArray.push({
164
+ name: file.name,
165
+ caption: null,
166
+ alternativeText: null,
167
+ folder: folderId
168
+ });
169
+ });
170
+ formData.append('fileInfo', JSON.stringify(fileInfoArray));
171
+ try {
172
+ await uploadFilesStream({
173
+ formData,
174
+ totalFiles: files.length
175
+ }).unwrap();
176
+ } catch (error) {
177
+ // Error is already dispatched to store from the API queryFn
178
+ }
179
+ };
180
+ const handleFileSelect = ()=>{
181
+ fileInputRef.current?.click();
182
+ };
183
+ const handleFileChange = async (e)=>{
184
+ const files = e.target.files;
185
+ if (files && files.length > 0) {
186
+ await uploadFilesToFolder(Array.from(files), null);
187
+ }
188
+ e.target.value = '';
189
+ };
190
+ const handleDrop = async (files)=>{
191
+ await uploadFilesToFolder(files, null);
192
+ };
193
+ return /*#__PURE__*/ jsxRuntime.jsx(UploadDropZoneContext.UploadDropZoneProvider, {
194
+ onDrop: handleDrop,
195
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
196
+ ref: uploadDropZoneRef,
197
+ children: /*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Layouts.Root, {
198
+ minHeight: "100vh",
199
+ background: "neutral0",
200
+ children: [
201
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
202
+ children: /*#__PURE__*/ jsxRuntime.jsx("input", {
203
+ type: "file",
204
+ ref: fileInputRef,
205
+ onChange: handleFileChange,
206
+ multiple: true
207
+ })
208
+ }),
209
+ /*#__PURE__*/ jsxRuntime.jsx(HeaderWrapper, {
210
+ children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Layouts.Header, {
211
+ title: "TODO: Folder name",
212
+ primaryAction: /*#__PURE__*/ jsxRuntime.jsx(designSystem.SimpleMenu, {
213
+ popoverPlacement: "bottom-end",
214
+ variant: "default",
215
+ endIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.ChevronDown, {}),
216
+ label: formatMessage({
217
+ id: translations.getTranslationKey('new'),
218
+ defaultMessage: 'New'
219
+ }),
220
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.MenuItem, {
221
+ onSelect: handleFileSelect,
222
+ startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Files, {}),
223
+ children: formatMessage({
224
+ id: translations.getTranslationKey('import-files'),
225
+ defaultMessage: 'Import files'
226
+ })
227
+ })
228
+ }),
229
+ subtitle: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
230
+ justifyContent: "space-between",
231
+ alignItems: "center",
232
+ gap: 4,
233
+ width: "100%",
234
+ children: [
235
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
236
+ gap: 4,
237
+ alignItems: "center",
238
+ children: "TODO: Filters and search"
239
+ }),
240
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
241
+ gap: 4,
242
+ alignItems: "center",
243
+ children: [
244
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
245
+ children: "TODO: Sort"
246
+ }),
247
+ /*#__PURE__*/ jsxRuntime.jsxs(StyledToggleGroup, {
248
+ type: "single",
249
+ value: isGridView ? 'grid' : 'table',
250
+ onValueChange: (value)=>value && setView(value === 'grid' ? constants.viewOptions.GRID : constants.viewOptions.TABLE),
251
+ "aria-label": formatMessage({
252
+ id: translations.getTranslationKey('view.switch.label'),
253
+ defaultMessage: 'View options'
254
+ }),
255
+ children: [
256
+ /*#__PURE__*/ jsxRuntime.jsxs(StyledToggleItem, {
257
+ value: "table",
258
+ "aria-label": formatMessage({
259
+ id: translations.getTranslationKey('view.table'),
260
+ defaultMessage: 'Table view'
261
+ }),
262
+ children: [
263
+ /*#__PURE__*/ jsxRuntime.jsx(icons.List, {}),
264
+ formatMessage({
265
+ id: translations.getTranslationKey('view.table'),
266
+ defaultMessage: 'Table view'
267
+ })
268
+ ]
269
+ }),
270
+ /*#__PURE__*/ jsxRuntime.jsxs(StyledToggleItem, {
271
+ value: "grid",
272
+ "aria-label": formatMessage({
273
+ id: translations.getTranslationKey('view.grid'),
274
+ defaultMessage: 'Grid view'
275
+ }),
276
+ children: [
277
+ /*#__PURE__*/ jsxRuntime.jsx(icons.GridFour, {}),
278
+ formatMessage({
279
+ id: translations.getTranslationKey('view.grid'),
280
+ defaultMessage: 'Grid view'
281
+ })
282
+ ]
283
+ })
284
+ ]
285
+ })
286
+ ]
287
+ })
288
+ ]
289
+ })
290
+ })
291
+ }),
292
+ /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Layouts.Content, {
293
+ children: /*#__PURE__*/ jsxRuntime.jsxs(UploadDropZone.DropZoneWithOverlay, {
294
+ children: [
295
+ /*#__PURE__*/ jsxRuntime.jsx(UploadDropZone.DropFilesMessage, {
296
+ uploadDropZoneRef: uploadDropZoneRef
297
+ }),
298
+ /*#__PURE__*/ jsxRuntime.jsx(AssetsView, {
299
+ view: view
300
+ })
301
+ ]
302
+ })
303
+ })
304
+ ]
305
+ })
306
+ })
307
+ });
308
+ };
309
+
310
+ exports.AssetsPage = AssetsPage;
311
+ //# sourceMappingURL=AssetsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetsPage.js","sources":["../../../../../admin/src/future/pages/Assets/AssetsPage.tsx"],"sourcesContent":["import { useRef, useCallback, type ChangeEvent } from 'react';\n\nimport * as ToggleGroup from '@radix-ui/react-toggle-group';\nimport { Layouts, useElementOnScreen, usePersistentState } from '@strapi/admin/strapi-admin';\nimport {\n Box,\n Flex,\n Loader,\n MenuItem,\n SimpleMenu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { ChevronDown, Files, GridFour as GridIcon, List } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useUploadFilesStreamMutation } from '../../services/api';\nimport { getTranslationKey } from '../../utils/translations';\n\nimport { AssetsGrid } from './components/AssetsGrid';\nimport { AssetsTable } from './components/AssetsTable';\nimport { DropFilesMessage, DropZoneWithOverlay } from './components/DropZone/UploadDropZone';\nimport { UploadDropZoneProvider } from './components/DropZone/UploadDropZoneContext';\nimport { localStorageKeys, viewOptions } from './constants';\nimport { useInfiniteAssets } from './hooks/useInfiniteAssets';\n\nconst INTERSECTION_OPTIONS: IntersectionObserverInit = { threshold: 0.1 };\n\nimport type { UploadFileInfo } from '../../../../../shared/contracts/files';\n\n/* -------------------------------------------------------------------------------------------------\n * AssetsView\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsViewProps {\n view: number;\n}\n\nconst AssetsView = ({ view }: AssetsViewProps) => {\n const { formatMessage } = useIntl();\n const { assets, isLoading, isFetchingMore, hasNextPage, fetchNextPage, error } =\n useInfiniteAssets();\n\n const isGridView = view === viewOptions.GRID;\n\n const loadMoreRef = useElementOnScreen<HTMLDivElement>(\n useCallback(\n (isVisible) => {\n if (isVisible && hasNextPage && !isFetchingMore) {\n fetchNextPage();\n }\n },\n [hasNextPage, isFetchingMore, fetchNextPage]\n ),\n INTERSECTION_OPTIONS\n );\n\n if (isLoading) {\n return (\n <Flex justifyContent=\"center\" padding={8}>\n <Loader>{formatMessage({ id: 'app.loading', defaultMessage: 'Loading...' })}</Loader>\n </Flex>\n );\n }\n\n if (error) {\n return (\n <Box padding={8}>\n <Typography textColor=\"danger600\">\n {formatMessage({\n id: getTranslationKey('list.assets.error'),\n defaultMessage: 'An error occurred while fetching assets.',\n })}\n </Typography>\n </Box>\n );\n }\n\n return (\n <>\n {isGridView ? <AssetsGrid assets={assets} /> : <AssetsTable assets={assets} />}\n <div ref={loadMoreRef} style={{ height: 1 }} />\n {isFetchingMore && (\n <Flex justifyContent=\"center\" padding={4}>\n <Loader>\n {formatMessage({\n id: getTranslationKey('list.assets.loading-more'),\n defaultMessage: 'Loading more assets...',\n })}\n </Loader>\n </Flex>\n )}\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * AssetsPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst StyledToggleGroup = styled(ToggleGroup.Root)`\n display: flex;\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n overflow: hidden;\n`;\n\nconst StyledToggleItem = styled(ToggleGroup.Item)`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[4]}`};\n border: none;\n background: ${({ theme }) => theme.colors.neutral0};\n color: ${({ theme }) => theme.colors.neutral800};\n cursor: pointer;\n font-size: ${({ theme }) => theme.fontSizes[1]};\n font-weight: ${({ theme }) => theme.fontWeights.semiBold};\n\n &:hover {\n background: ${({ theme }) => theme.colors.neutral100};\n }\n\n &[data-state='on'] {\n background: ${({ theme }) => theme.colors.neutral150};\n }\n\n svg {\n width: 1.6rem;\n height: 1.6rem;\n }\n`;\n\nconst HeaderWrapper = styled.div`\n [data-strapi-header] {\n background: ${({ theme }) => theme.colors.neutral0};\n\n h1 {\n font-size: 1.8rem;\n }\n }\n`;\n\nexport const AssetsPage = () => {\n const { formatMessage } = useIntl();\n\n // View state\n const [view, setView] = usePersistentState(localStorageKeys.view, viewOptions.GRID);\n const isGridView = view === viewOptions.GRID;\n\n // Refs\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadDropZoneRef = useRef<HTMLDivElement>(null);\n\n // Upload handlers\n const [uploadFilesStream] = useUploadFilesStreamMutation();\n\n const uploadFilesToFolder = async (files: globalThis.File[], folderId: number | null) => {\n if (files.length === 0) return;\n\n const formData = new FormData();\n const fileInfoArray: UploadFileInfo[] = [];\n\n files.forEach((file) => {\n formData.append('files', file);\n fileInfoArray.push({\n name: file.name,\n caption: null,\n alternativeText: null,\n folder: folderId,\n });\n });\n\n formData.append('fileInfo', JSON.stringify(fileInfoArray));\n try {\n await uploadFilesStream({ formData, totalFiles: files.length }).unwrap();\n } catch (error) {\n // Error is already dispatched to store from the API queryFn\n }\n };\n\n const handleFileSelect = () => {\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (e: ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (files && files.length > 0) {\n await uploadFilesToFolder(Array.from(files), null);\n }\n e.target.value = '';\n };\n\n const handleDrop = async (files: globalThis.File[]) => {\n await uploadFilesToFolder(files, null);\n };\n\n return (\n <UploadDropZoneProvider onDrop={handleDrop}>\n <Box ref={uploadDropZoneRef}>\n <Layouts.Root minHeight=\"100vh\" background=\"neutral0\">\n <VisuallyHidden>\n <input type=\"file\" ref={fileInputRef} onChange={handleFileChange} multiple />\n </VisuallyHidden>\n\n <HeaderWrapper>\n <Layouts.Header\n title=\"TODO: Folder name\"\n primaryAction={\n <SimpleMenu\n popoverPlacement=\"bottom-end\"\n variant=\"default\"\n endIcon={<ChevronDown />}\n label={formatMessage({ id: getTranslationKey('new'), defaultMessage: 'New' })}\n >\n <MenuItem onSelect={handleFileSelect} startIcon={<Files />}>\n {formatMessage({\n id: getTranslationKey('import-files'),\n defaultMessage: 'Import files',\n })}\n </MenuItem>\n </SimpleMenu>\n }\n subtitle={\n <Flex justifyContent=\"space-between\" alignItems=\"center\" gap={4} width=\"100%\">\n <Flex gap={4} alignItems=\"center\">\n TODO: Filters and search\n </Flex>\n\n <Flex gap={4} alignItems=\"center\">\n <Box>TODO: Sort</Box>\n <StyledToggleGroup\n type=\"single\"\n value={isGridView ? 'grid' : 'table'}\n onValueChange={(value) =>\n value && setView(value === 'grid' ? viewOptions.GRID : viewOptions.TABLE)\n }\n aria-label={formatMessage({\n id: getTranslationKey('view.switch.label'),\n defaultMessage: 'View options',\n })}\n >\n <StyledToggleItem\n value=\"table\"\n aria-label={formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\n >\n <List />\n {formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\n </StyledToggleItem>\n <StyledToggleItem\n value=\"grid\"\n aria-label={formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n >\n <GridIcon />\n {formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n </StyledToggleItem>\n </StyledToggleGroup>\n </Flex>\n </Flex>\n }\n />\n </HeaderWrapper>\n\n <Layouts.Content>\n <DropZoneWithOverlay>\n <DropFilesMessage uploadDropZoneRef={uploadDropZoneRef} />\n <AssetsView view={view} />\n </DropZoneWithOverlay>\n </Layouts.Content>\n </Layouts.Root>\n </Box>\n </UploadDropZoneProvider>\n );\n};\n"],"names":["INTERSECTION_OPTIONS","threshold","AssetsView","view","formatMessage","useIntl","assets","isLoading","isFetchingMore","hasNextPage","fetchNextPage","error","useInfiniteAssets","isGridView","viewOptions","GRID","loadMoreRef","useElementOnScreen","useCallback","isVisible","_jsx","Flex","justifyContent","padding","Loader","id","defaultMessage","Box","Typography","textColor","getTranslationKey","_jsxs","_Fragment","AssetsGrid","AssetsTable","div","ref","style","height","StyledToggleGroup","styled","ToggleGroup","Root","theme","colors","neutral200","borderRadius","StyledToggleItem","Item","spaces","neutral0","neutral800","fontSizes","fontWeights","semiBold","neutral100","neutral150","HeaderWrapper","AssetsPage","setView","usePersistentState","localStorageKeys","fileInputRef","useRef","uploadDropZoneRef","uploadFilesStream","useUploadFilesStreamMutation","uploadFilesToFolder","files","folderId","length","formData","FormData","fileInfoArray","forEach","file","append","push","name","caption","alternativeText","folder","JSON","stringify","totalFiles","unwrap","handleFileSelect","current","click","handleFileChange","e","target","Array","from","value","handleDrop","UploadDropZoneProvider","onDrop","Layouts","minHeight","background","VisuallyHidden","input","type","onChange","multiple","Header","title","primaryAction","SimpleMenu","popoverPlacement","variant","endIcon","ChevronDown","label","MenuItem","onSelect","startIcon","Files","subtitle","alignItems","gap","width","onValueChange","TABLE","aria-label","List","GridIcon","Content","DropZoneWithOverlay","DropFilesMessage"],"mappings":"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"}
@@ -0,0 +1,290 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useRef, useCallback } from 'react';
3
+ import * as ToggleGroup from '@radix-ui/react-toggle-group';
4
+ import { usePersistentState, Layouts, useElementOnScreen } from '@strapi/admin/strapi-admin';
5
+ import { Box, VisuallyHidden, SimpleMenu, MenuItem, Flex, Loader, Typography } from '@strapi/design-system';
6
+ import { ChevronDown, Files, List, GridFour } from '@strapi/icons';
7
+ import { useIntl } from 'react-intl';
8
+ import { styled } from 'styled-components';
9
+ import { useUploadFilesStreamMutation } from '../../services/api.mjs';
10
+ import { getTranslationKey } from '../../utils/translations.mjs';
11
+ import { AssetsGrid } from './components/AssetsGrid.mjs';
12
+ import { AssetsTable } from './components/AssetsTable.mjs';
13
+ import { DropZoneWithOverlay, DropFilesMessage } from './components/DropZone/UploadDropZone.mjs';
14
+ import { UploadDropZoneProvider } from './components/DropZone/UploadDropZoneContext.mjs';
15
+ import { localStorageKeys, viewOptions } from './constants.mjs';
16
+ import { useInfiniteAssets } from './hooks/useInfiniteAssets.mjs';
17
+
18
+ const INTERSECTION_OPTIONS = {
19
+ threshold: 0.1
20
+ };
21
+ const AssetsView = ({ view })=>{
22
+ const { formatMessage } = useIntl();
23
+ const { assets, isLoading, isFetchingMore, hasNextPage, fetchNextPage, error } = useInfiniteAssets();
24
+ const isGridView = view === viewOptions.GRID;
25
+ const loadMoreRef = useElementOnScreen(useCallback((isVisible)=>{
26
+ if (isVisible && hasNextPage && !isFetchingMore) {
27
+ fetchNextPage();
28
+ }
29
+ }, [
30
+ hasNextPage,
31
+ isFetchingMore,
32
+ fetchNextPage
33
+ ]), INTERSECTION_OPTIONS);
34
+ if (isLoading) {
35
+ return /*#__PURE__*/ jsx(Flex, {
36
+ justifyContent: "center",
37
+ padding: 8,
38
+ children: /*#__PURE__*/ jsx(Loader, {
39
+ children: formatMessage({
40
+ id: 'app.loading',
41
+ defaultMessage: 'Loading...'
42
+ })
43
+ })
44
+ });
45
+ }
46
+ if (error) {
47
+ return /*#__PURE__*/ jsx(Box, {
48
+ padding: 8,
49
+ children: /*#__PURE__*/ jsx(Typography, {
50
+ textColor: "danger600",
51
+ children: formatMessage({
52
+ id: getTranslationKey('list.assets.error'),
53
+ defaultMessage: 'An error occurred while fetching assets.'
54
+ })
55
+ })
56
+ });
57
+ }
58
+ return /*#__PURE__*/ jsxs(Fragment, {
59
+ children: [
60
+ isGridView ? /*#__PURE__*/ jsx(AssetsGrid, {
61
+ assets: assets
62
+ }) : /*#__PURE__*/ jsx(AssetsTable, {
63
+ assets: assets
64
+ }),
65
+ /*#__PURE__*/ jsx("div", {
66
+ ref: loadMoreRef,
67
+ style: {
68
+ height: 1
69
+ }
70
+ }),
71
+ isFetchingMore && /*#__PURE__*/ jsx(Flex, {
72
+ justifyContent: "center",
73
+ padding: 4,
74
+ children: /*#__PURE__*/ jsx(Loader, {
75
+ children: formatMessage({
76
+ id: getTranslationKey('list.assets.loading-more'),
77
+ defaultMessage: 'Loading more assets...'
78
+ })
79
+ })
80
+ })
81
+ ]
82
+ });
83
+ };
84
+ /* -------------------------------------------------------------------------------------------------
85
+ * AssetsPage
86
+ * -----------------------------------------------------------------------------------------------*/ const StyledToggleGroup = styled(ToggleGroup.Root)`
87
+ display: flex;
88
+ border: 1px solid ${({ theme })=>theme.colors.neutral200};
89
+ border-radius: ${({ theme })=>theme.borderRadius};
90
+ overflow: hidden;
91
+ `;
92
+ const StyledToggleItem = styled(ToggleGroup.Item)`
93
+ display: flex;
94
+ align-items: center;
95
+ gap: ${({ theme })=>theme.spaces[2]};
96
+ padding: ${({ theme })=>`${theme.spaces[2]} ${theme.spaces[4]}`};
97
+ border: none;
98
+ background: ${({ theme })=>theme.colors.neutral0};
99
+ color: ${({ theme })=>theme.colors.neutral800};
100
+ cursor: pointer;
101
+ font-size: ${({ theme })=>theme.fontSizes[1]};
102
+ font-weight: ${({ theme })=>theme.fontWeights.semiBold};
103
+
104
+ &:hover {
105
+ background: ${({ theme })=>theme.colors.neutral100};
106
+ }
107
+
108
+ &[data-state='on'] {
109
+ background: ${({ theme })=>theme.colors.neutral150};
110
+ }
111
+
112
+ svg {
113
+ width: 1.6rem;
114
+ height: 1.6rem;
115
+ }
116
+ `;
117
+ const HeaderWrapper = styled.div`
118
+ [data-strapi-header] {
119
+ background: ${({ theme })=>theme.colors.neutral0};
120
+
121
+ h1 {
122
+ font-size: 1.8rem;
123
+ }
124
+ }
125
+ `;
126
+ const AssetsPage = ()=>{
127
+ const { formatMessage } = useIntl();
128
+ // View state
129
+ const [view, setView] = usePersistentState(localStorageKeys.view, viewOptions.GRID);
130
+ const isGridView = view === viewOptions.GRID;
131
+ // Refs
132
+ const fileInputRef = useRef(null);
133
+ const uploadDropZoneRef = useRef(null);
134
+ // Upload handlers
135
+ const [uploadFilesStream] = useUploadFilesStreamMutation();
136
+ const uploadFilesToFolder = async (files, folderId)=>{
137
+ if (files.length === 0) return;
138
+ const formData = new FormData();
139
+ const fileInfoArray = [];
140
+ files.forEach((file)=>{
141
+ formData.append('files', file);
142
+ fileInfoArray.push({
143
+ name: file.name,
144
+ caption: null,
145
+ alternativeText: null,
146
+ folder: folderId
147
+ });
148
+ });
149
+ formData.append('fileInfo', JSON.stringify(fileInfoArray));
150
+ try {
151
+ await uploadFilesStream({
152
+ formData,
153
+ totalFiles: files.length
154
+ }).unwrap();
155
+ } catch (error) {
156
+ // Error is already dispatched to store from the API queryFn
157
+ }
158
+ };
159
+ const handleFileSelect = ()=>{
160
+ fileInputRef.current?.click();
161
+ };
162
+ const handleFileChange = async (e)=>{
163
+ const files = e.target.files;
164
+ if (files && files.length > 0) {
165
+ await uploadFilesToFolder(Array.from(files), null);
166
+ }
167
+ e.target.value = '';
168
+ };
169
+ const handleDrop = async (files)=>{
170
+ await uploadFilesToFolder(files, null);
171
+ };
172
+ return /*#__PURE__*/ jsx(UploadDropZoneProvider, {
173
+ onDrop: handleDrop,
174
+ children: /*#__PURE__*/ jsx(Box, {
175
+ ref: uploadDropZoneRef,
176
+ children: /*#__PURE__*/ jsxs(Layouts.Root, {
177
+ minHeight: "100vh",
178
+ background: "neutral0",
179
+ children: [
180
+ /*#__PURE__*/ jsx(VisuallyHidden, {
181
+ children: /*#__PURE__*/ jsx("input", {
182
+ type: "file",
183
+ ref: fileInputRef,
184
+ onChange: handleFileChange,
185
+ multiple: true
186
+ })
187
+ }),
188
+ /*#__PURE__*/ jsx(HeaderWrapper, {
189
+ children: /*#__PURE__*/ jsx(Layouts.Header, {
190
+ title: "TODO: Folder name",
191
+ primaryAction: /*#__PURE__*/ jsx(SimpleMenu, {
192
+ popoverPlacement: "bottom-end",
193
+ variant: "default",
194
+ endIcon: /*#__PURE__*/ jsx(ChevronDown, {}),
195
+ label: formatMessage({
196
+ id: getTranslationKey('new'),
197
+ defaultMessage: 'New'
198
+ }),
199
+ children: /*#__PURE__*/ jsx(MenuItem, {
200
+ onSelect: handleFileSelect,
201
+ startIcon: /*#__PURE__*/ jsx(Files, {}),
202
+ children: formatMessage({
203
+ id: getTranslationKey('import-files'),
204
+ defaultMessage: 'Import files'
205
+ })
206
+ })
207
+ }),
208
+ subtitle: /*#__PURE__*/ jsxs(Flex, {
209
+ justifyContent: "space-between",
210
+ alignItems: "center",
211
+ gap: 4,
212
+ width: "100%",
213
+ children: [
214
+ /*#__PURE__*/ jsx(Flex, {
215
+ gap: 4,
216
+ alignItems: "center",
217
+ children: "TODO: Filters and search"
218
+ }),
219
+ /*#__PURE__*/ jsxs(Flex, {
220
+ gap: 4,
221
+ alignItems: "center",
222
+ children: [
223
+ /*#__PURE__*/ jsx(Box, {
224
+ children: "TODO: Sort"
225
+ }),
226
+ /*#__PURE__*/ jsxs(StyledToggleGroup, {
227
+ type: "single",
228
+ value: isGridView ? 'grid' : 'table',
229
+ onValueChange: (value)=>value && setView(value === 'grid' ? viewOptions.GRID : viewOptions.TABLE),
230
+ "aria-label": formatMessage({
231
+ id: getTranslationKey('view.switch.label'),
232
+ defaultMessage: 'View options'
233
+ }),
234
+ children: [
235
+ /*#__PURE__*/ jsxs(StyledToggleItem, {
236
+ value: "table",
237
+ "aria-label": formatMessage({
238
+ id: getTranslationKey('view.table'),
239
+ defaultMessage: 'Table view'
240
+ }),
241
+ children: [
242
+ /*#__PURE__*/ jsx(List, {}),
243
+ formatMessage({
244
+ id: getTranslationKey('view.table'),
245
+ defaultMessage: 'Table view'
246
+ })
247
+ ]
248
+ }),
249
+ /*#__PURE__*/ jsxs(StyledToggleItem, {
250
+ value: "grid",
251
+ "aria-label": formatMessage({
252
+ id: getTranslationKey('view.grid'),
253
+ defaultMessage: 'Grid view'
254
+ }),
255
+ children: [
256
+ /*#__PURE__*/ jsx(GridFour, {}),
257
+ formatMessage({
258
+ id: getTranslationKey('view.grid'),
259
+ defaultMessage: 'Grid view'
260
+ })
261
+ ]
262
+ })
263
+ ]
264
+ })
265
+ ]
266
+ })
267
+ ]
268
+ })
269
+ })
270
+ }),
271
+ /*#__PURE__*/ jsx(Layouts.Content, {
272
+ children: /*#__PURE__*/ jsxs(DropZoneWithOverlay, {
273
+ children: [
274
+ /*#__PURE__*/ jsx(DropFilesMessage, {
275
+ uploadDropZoneRef: uploadDropZoneRef
276
+ }),
277
+ /*#__PURE__*/ jsx(AssetsView, {
278
+ view: view
279
+ })
280
+ ]
281
+ })
282
+ })
283
+ ]
284
+ })
285
+ })
286
+ });
287
+ };
288
+
289
+ export { AssetsPage };
290
+ //# sourceMappingURL=AssetsPage.mjs.map