@strapi/upload 5.47.1 → 5.48.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.
- package/dist/admin/components/EditAssetDialog/EditAssetContent.js +12 -2
- package/dist/admin/components/EditAssetDialog/EditAssetContent.js.map +1 -1
- package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs +12 -2
- package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs.map +1 -1
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js +1 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js.map +1 -1
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs +1 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs.map +1 -1
- package/dist/admin/future/components/Drawer.js +7 -8
- package/dist/admin/future/components/Drawer.js.map +1 -1
- package/dist/admin/future/components/Drawer.mjs +7 -8
- package/dist/admin/future/components/Drawer.mjs.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.js +33 -29
- package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.mjs +36 -32
- package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.js +2 -2
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +3 -3
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +626 -169
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +630 -175
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js +25 -5
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs +25 -5
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs.map +1 -1
- package/dist/admin/future/services/api.js +124 -200
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +124 -200
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +57 -1
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +56 -2
- package/dist/admin/future/services/assets.mjs.map +1 -1
- package/dist/admin/future/services/settings.js +18 -0
- package/dist/admin/future/services/settings.js.map +1 -0
- package/dist/admin/future/services/settings.mjs +16 -0
- package/dist/admin/future/services/settings.mjs.map +1 -0
- package/dist/admin/future/services/uploadFileViaXHR.js +92 -0
- package/dist/admin/future/services/uploadFileViaXHR.js.map +1 -0
- package/dist/admin/future/services/uploadFileViaXHR.mjs +88 -0
- package/dist/admin/future/services/uploadFileViaXHR.mjs.map +1 -0
- package/dist/admin/future/store/uploadProgress.js +32 -26
- package/dist/admin/future/store/uploadProgress.js.map +1 -1
- package/dist/admin/future/store/uploadProgress.mjs +32 -27
- package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
- package/dist/admin/future/utils/createRafBatcher.js +42 -0
- package/dist/admin/future/utils/createRafBatcher.js.map +1 -0
- package/dist/admin/future/utils/createRafBatcher.mjs +40 -0
- package/dist/admin/future/utils/createRafBatcher.mjs.map +1 -0
- package/dist/admin/future/utils/downloadFile.js +19 -0
- package/dist/admin/future/utils/downloadFile.js.map +1 -0
- package/dist/admin/future/utils/downloadFile.mjs +17 -0
- package/dist/admin/future/utils/downloadFile.mjs.map +1 -0
- package/dist/admin/hooks/useAssets.js +5 -3
- package/dist/admin/hooks/useAssets.js.map +1 -1
- package/dist/admin/hooks/useAssets.mjs +5 -3
- package/dist/admin/hooks/useAssets.mjs.map +1 -1
- package/dist/admin/src/components/EditAssetDialog/EditAssetContent.d.ts +2 -1
- package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +15 -1
- package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetPreview.d.ts +4 -1
- package/dist/admin/src/future/services/api.d.ts +9 -8
- package/dist/admin/src/future/services/assets.d.ts +6 -1
- package/dist/admin/src/future/services/uploadFileViaXHR.d.ts +34 -0
- package/dist/admin/src/future/store/uploadProgress.d.ts +17 -4
- package/dist/admin/src/future/utils/createRafBatcher.d.ts +23 -0
- package/dist/admin/src/future/utils/downloadFile.d.ts +6 -0
- package/dist/admin/translations/en.json.js +21 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +21 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +69 -118
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +69 -118
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/controllers/content-api.js +12 -0
- package/dist/server/controllers/content-api.js.map +1 -1
- package/dist/server/controllers/content-api.mjs +12 -0
- package/dist/server/controllers/content-api.mjs.map +1 -1
- package/dist/server/routes/admin.js +2 -2
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +2 -2
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/routes/content-api.js +15 -0
- package/dist/server/routes/content-api.js.map +1 -1
- package/dist/server/routes/content-api.mjs +15 -0
- package/dist/server/routes/content-api.mjs.map +1 -1
- package/dist/server/routes/validation/upload.js +28 -0
- package/dist/server/routes/validation/upload.js.map +1 -1
- package/dist/server/routes/validation/upload.mjs +28 -0
- package/dist/server/routes/validation/upload.mjs.map +1 -1
- package/dist/server/services/image-manipulation.js +16 -8
- package/dist/server/services/image-manipulation.js.map +1 -1
- package/dist/server/services/image-manipulation.mjs +16 -8
- package/dist/server/services/image-manipulation.mjs.map +1 -1
- package/dist/server/services/upload.js +90 -1
- package/dist/server/services/upload.js.map +1 -1
- package/dist/server/services/upload.mjs +91 -2
- package/dist/server/services/upload.mjs.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +6 -8
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/content-api.d.ts +1 -0
- package/dist/server/src/controllers/content-api.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +2 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +6 -1
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/routes/content-api.d.ts.map +1 -1
- package/dist/server/src/routes/validation/upload.d.ts +45 -0
- package/dist/server/src/routes/validation/upload.d.ts.map +1 -1
- package/dist/server/src/services/image-manipulation.d.ts +5 -0
- package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -0
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/upload.d.ts +5 -0
- package/dist/server/src/services/upload.d.ts.map +1 -1
- package/dist/server/src/types.d.ts +2 -2
- package/dist/server/src/types.d.ts.map +1 -1
- package/dist/shared/contracts/files.d.ts +19 -2
- package/dist/shared/contracts/files.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadProgress.js","sources":["../../../../admin/src/future/store/uploadProgress.ts"],"sourcesContent":["import { createSlice, type PayloadAction } from '@reduxjs/toolkit';\n\nimport type { File } from '../../../../shared/contracts/files';\n\nexport interface FileUploadError {\n name: string;\n message: string;\n}\n\nexport type FileProgressStatus = 'pending' | 'uploading' | 'complete' | 'error' | 'cancelled';\n\nexport interface FileProgress {\n name: string;\n index: number;\n status: FileProgressStatus;\n size: number;\n file?: File;\n error?: string;\n}\n\nexport interface UploadProgressState {\n isVisible: boolean;\n isMinimized: boolean;\n progress: number;\n totalFiles: number;\n files: FileProgress[];\n errors: FileUploadError[];\n uploadId: number;\n}\n\nexport interface RootState {\n uploadProgress: UploadProgressState;\n}\n\nconst initialState: UploadProgressState = {\n isVisible: false,\n isMinimized: false,\n progress: 0,\n totalFiles: 0,\n files: [],\n errors: [],\n uploadId: 0,\n};\n\nconst computeProgress = (files: FileProgress[]): number => {\n if (files.length === 0) return 0;\n const totalSize = files.reduce((sum, f) => sum + f.size, 0);\n if (totalSize === 0) {\n // Fallback to count-based if sizes are unknown\n const completed = files.filter(\n (f) => f.status === 'complete' || f.status === 'error' || f.status === 'cancelled'\n ).length;\n return Math.round((completed / files.length) * 100);\n }\n const completedSize = files\n .filter((f) => f.status === 'complete' || f.status === 'error' || f.status === 'cancelled')\n .reduce((sum, f) => sum + f.size, 0);\n return Math.round((completedSize / totalSize) * 100);\n};\n\nconst uploadProgressSlice = createSlice({\n name: 'uploadProgress',\n initialState,\n reducers: {\n openUploadProgress(\n state,\n action: PayloadAction<{\n totalFiles: number;\n fileNames: string[];\n fileSizes?: number[];\n }>\n ) {\n state.isVisible = true;\n state.isMinimized = false;\n state.progress = 0;\n\n // Create pending files for upload\n const pendingFiles: FileProgress[] = action.payload.fileNames.map((name, index) => ({\n name,\n index,\n status: 'pending' as FileProgressStatus,\n size: action.payload.fileSizes?.[index] ?? 0,\n }));\n\n state.files = pendingFiles;\n state.totalFiles = action.payload.totalFiles;\n state.errors = [];\n state.uploadId += 1;\n },\n setFileUploading(\n state,\n action: PayloadAction<{ name: string; index: number; total: number; size: number }>\n ) {\n const { index, size } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'uploading';\n state.files[index].size = size;\n }\n },\n setFileComplete(state, action: PayloadAction<{ index: number; file: File }>) {\n const { index, file } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'complete';\n state.files[index].file = file;\n }\n state.progress = computeProgress(state.files);\n },\n setFileError(state, action: PayloadAction<{ index: number; name: string; message: string }>) {\n const { index, name, message } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'error';\n state.files[index].error = message;\n }\n state.errors = [...state.errors, { name, message }];\n state.progress = computeProgress(state.files);\n },\n updateProgress(state, action: PayloadAction<number>) {\n state.progress = action.payload;\n },\n addUploadErrors(state, action: PayloadAction<FileUploadError[]>) {\n state.errors = [...state.errors, ...action.payload];\n },\n closeUploadProgress(state) {\n state.isVisible = false;\n state.isMinimized = false;\n state.progress = 0;\n state.totalFiles = 0;\n state.files = [];\n state.errors = [];\n },\n toggleMinimize(state) {\n state.isMinimized = !state.isMinimized;\n },\n cancelUpload(state) {\n // Mark all pending and uploading files as cancelled\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return { ...file, status: 'cancelled' as FileProgressStatus };\n }\n return file;\n });\n state.progress = computeProgress(state.files);\n },\n setUploadFailed(state, action: PayloadAction<{ message: string }>) {\n // Mark all pending and uploading files as errored when a catastrophic failure occurs\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return {\n ...file,\n status: 'error' as FileProgressStatus,\n error: action.payload.message,\n };\n }\n return file;\n });\n state.progress = 100;\n state.errors = [...state.errors, { name: 'Upload Error', message: action.payload.message }];\n },\n retryCancelledFiles(state) {\n // Reset all cancelled files back to pending for retry\n state.files = state.files.map((file) => {\n if (file.status === 'cancelled') {\n return {\n ...file,\n status: 'pending' as FileProgressStatus,\n };\n }\n return file;\n });\n state.progress = computeProgress(state.files);\n },\n },\n});\n\nexport const {\n openUploadProgress,\n setFileUploading,\n setFileComplete,\n setFileError,\n updateProgress,\n addUploadErrors,\n closeUploadProgress,\n toggleMinimize,\n cancelUpload,\n setUploadFailed,\n retryCancelledFiles,\n} = uploadProgressSlice.actions;\n\nexport const uploadProgressReducer = uploadProgressSlice.reducer;\n"],"names":["initialState","isVisible","isMinimized","progress","totalFiles","files","errors","uploadId","computeProgress","length","totalSize","reduce","sum","f","size","completed","filter","status","Math","round","completedSize","uploadProgressSlice","createSlice","name","reducers","openUploadProgress","state","action","pendingFiles","payload","fileNames","map","index","fileSizes","setFileUploading","setFileComplete","file","setFileError","message","error","updateProgress","addUploadErrors","closeUploadProgress","toggleMinimize","cancelUpload","setUploadFailed","retryCancelledFiles","actions","uploadProgressReducer","reducer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"uploadProgress.js","sources":["../../../../admin/src/future/store/uploadProgress.ts"],"sourcesContent":["import { createSelector, createSlice, type PayloadAction } from '@reduxjs/toolkit';\n\nimport type { File } from '../../../../shared/contracts/files';\n\nexport interface FileUploadError {\n name: string;\n message: string;\n}\n\nexport type FileProgressStatus = 'pending' | 'uploading' | 'complete' | 'error' | 'cancelled';\n\nexport interface FileProgress {\n name: string;\n index: number;\n status: FileProgressStatus;\n size: number;\n uploadedBytes: number;\n file?: File;\n error?: string;\n}\n\nexport interface UploadProgressState {\n isVisible: boolean;\n isMinimized: boolean;\n totalFiles: number;\n files: FileProgress[];\n errors: FileUploadError[];\n uploadId: number;\n}\n\nexport interface RootState {\n uploadProgress: UploadProgressState;\n}\n\nconst initialState: UploadProgressState = {\n isVisible: false,\n isMinimized: false,\n totalFiles: 0,\n files: [],\n errors: [],\n uploadId: 0,\n};\n\nconst uploadProgressSlice = createSlice({\n name: 'uploadProgress',\n initialState,\n reducers: {\n openUploadProgress(\n state,\n action: PayloadAction<{\n totalFiles: number;\n fileNames: string[];\n fileSizes?: number[];\n }>\n ) {\n state.isVisible = true;\n state.isMinimized = false;\n\n // Create pending files for upload\n const pendingFiles: FileProgress[] = action.payload.fileNames.map((name, index) => ({\n name,\n index,\n status: 'pending' as FileProgressStatus,\n size: action.payload.fileSizes?.[index] ?? 0,\n uploadedBytes: 0,\n }));\n\n state.files = pendingFiles;\n state.totalFiles = action.payload.totalFiles;\n state.errors = [];\n state.uploadId += 1;\n },\n setFileUploading(state, action: PayloadAction<{ name: string; index: number; size: number }>) {\n const { index, size } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'uploading';\n state.files[index].size = size;\n }\n },\n setFileProgress(state, action: PayloadAction<{ index: number; bytes: number }>) {\n const { index, bytes } = action.payload;\n const file = state.files[index];\n if (file) {\n // Clamp to the known file size so the aggregate can never exceed 100%.\n file.uploadedBytes = Math.min(bytes, file.size);\n }\n },\n setFileComplete(state, action: PayloadAction<{ index: number; file: File }>) {\n const { index, file } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'complete';\n state.files[index].file = file;\n // Reflect completion in the aggregate even if the final progress event was throttled.\n state.files[index].uploadedBytes = state.files[index].size;\n }\n },\n setFileError(state, action: PayloadAction<{ index: number; name: string; message: string }>) {\n const { index, name, message } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'error';\n state.files[index].error = message;\n }\n state.errors = [...state.errors, { name, message }];\n },\n addUploadErrors(state, action: PayloadAction<FileUploadError[]>) {\n state.errors = [...state.errors, ...action.payload];\n },\n closeUploadProgress(state) {\n state.isVisible = false;\n state.isMinimized = false;\n state.totalFiles = 0;\n state.files = [];\n state.errors = [];\n },\n toggleMinimize(state) {\n state.isMinimized = !state.isMinimized;\n },\n cancelUpload(state) {\n // Mark all pending and uploading files as cancelled\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return { ...file, status: 'cancelled' as FileProgressStatus };\n }\n return file;\n });\n },\n setUploadFailed(state, action: PayloadAction<{ message: string }>) {\n // Mark all pending and uploading files as errored when a catastrophic failure occurs\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return {\n ...file,\n status: 'error' as FileProgressStatus,\n error: action.payload.message,\n };\n }\n return file;\n });\n state.errors = [...state.errors, { name: 'Upload Error', message: action.payload.message }];\n },\n retryCancelledFiles(state) {\n // Reset all cancelled files back to pending for retry\n state.files = state.files.map((file) => {\n if (file.status === 'cancelled') {\n return {\n ...file,\n status: 'pending' as FileProgressStatus,\n uploadedBytes: 0,\n };\n }\n return file;\n });\n },\n },\n});\n\n/**\n * Byte-weighted aggregate progress across the whole batch: `sum(uploadedBytes) / sum(size)`.\n *\n * Falls back to count-based progress (settled files / total files) when all sizes are\n * zero — e.g. URL-flow rows where the file size is unknown up front.\n */\nexport const selectAggregateProgress = createSelector(\n (state: RootState) => state.uploadProgress.files,\n (files): number => {\n if (files.length === 0) return 0;\n\n const totalSize = files.reduce((sum, f) => sum + f.size, 0);\n\n if (totalSize === 0) {\n const settled = files.filter(\n (f) => f.status === 'complete' || f.status === 'error' || f.status === 'cancelled'\n ).length;\n return Math.round((settled / files.length) * 100);\n }\n\n const uploadedBytes = files.reduce((sum, f) => sum + f.uploadedBytes, 0);\n return Math.round((uploadedBytes / totalSize) * 100);\n }\n);\n\nexport const {\n openUploadProgress,\n setFileUploading,\n setFileProgress,\n setFileComplete,\n setFileError,\n addUploadErrors,\n closeUploadProgress,\n toggleMinimize,\n cancelUpload,\n setUploadFailed,\n retryCancelledFiles,\n} = uploadProgressSlice.actions;\n\nexport const uploadProgressReducer = uploadProgressSlice.reducer;\n"],"names":["initialState","isVisible","isMinimized","totalFiles","files","errors","uploadId","uploadProgressSlice","createSlice","name","reducers","openUploadProgress","state","action","pendingFiles","payload","fileNames","map","index","status","size","fileSizes","uploadedBytes","setFileUploading","setFileProgress","bytes","file","Math","min","setFileComplete","setFileError","message","error","addUploadErrors","closeUploadProgress","toggleMinimize","cancelUpload","setUploadFailed","retryCancelledFiles","selectAggregateProgress","createSelector","uploadProgress","length","totalSize","reduce","sum","f","settled","filter","round","actions","uploadProgressReducer","reducer"],"mappings":"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"}
|
|
@@ -1,25 +1,13 @@
|
|
|
1
|
-
import { createSlice } from '@reduxjs/toolkit';
|
|
1
|
+
import { createSlice, createSelector } from '@reduxjs/toolkit';
|
|
2
2
|
|
|
3
3
|
const initialState = {
|
|
4
4
|
isVisible: false,
|
|
5
5
|
isMinimized: false,
|
|
6
|
-
progress: 0,
|
|
7
6
|
totalFiles: 0,
|
|
8
7
|
files: [],
|
|
9
8
|
errors: [],
|
|
10
9
|
uploadId: 0
|
|
11
10
|
};
|
|
12
|
-
const computeProgress = (files)=>{
|
|
13
|
-
if (files.length === 0) return 0;
|
|
14
|
-
const totalSize = files.reduce((sum, f)=>sum + f.size, 0);
|
|
15
|
-
if (totalSize === 0) {
|
|
16
|
-
// Fallback to count-based if sizes are unknown
|
|
17
|
-
const completed = files.filter((f)=>f.status === 'complete' || f.status === 'error' || f.status === 'cancelled').length;
|
|
18
|
-
return Math.round(completed / files.length * 100);
|
|
19
|
-
}
|
|
20
|
-
const completedSize = files.filter((f)=>f.status === 'complete' || f.status === 'error' || f.status === 'cancelled').reduce((sum, f)=>sum + f.size, 0);
|
|
21
|
-
return Math.round(completedSize / totalSize * 100);
|
|
22
|
-
};
|
|
23
11
|
const uploadProgressSlice = createSlice({
|
|
24
12
|
name: 'uploadProgress',
|
|
25
13
|
initialState,
|
|
@@ -27,13 +15,13 @@ const uploadProgressSlice = createSlice({
|
|
|
27
15
|
openUploadProgress (state, action) {
|
|
28
16
|
state.isVisible = true;
|
|
29
17
|
state.isMinimized = false;
|
|
30
|
-
state.progress = 0;
|
|
31
18
|
// Create pending files for upload
|
|
32
19
|
const pendingFiles = action.payload.fileNames.map((name, index)=>({
|
|
33
20
|
name,
|
|
34
21
|
index,
|
|
35
22
|
status: 'pending',
|
|
36
|
-
size: action.payload.fileSizes?.[index] ?? 0
|
|
23
|
+
size: action.payload.fileSizes?.[index] ?? 0,
|
|
24
|
+
uploadedBytes: 0
|
|
37
25
|
}));
|
|
38
26
|
state.files = pendingFiles;
|
|
39
27
|
state.totalFiles = action.payload.totalFiles;
|
|
@@ -47,13 +35,22 @@ const uploadProgressSlice = createSlice({
|
|
|
47
35
|
state.files[index].size = size;
|
|
48
36
|
}
|
|
49
37
|
},
|
|
38
|
+
setFileProgress (state, action) {
|
|
39
|
+
const { index, bytes } = action.payload;
|
|
40
|
+
const file = state.files[index];
|
|
41
|
+
if (file) {
|
|
42
|
+
// Clamp to the known file size so the aggregate can never exceed 100%.
|
|
43
|
+
file.uploadedBytes = Math.min(bytes, file.size);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
50
46
|
setFileComplete (state, action) {
|
|
51
47
|
const { index, file } = action.payload;
|
|
52
48
|
if (state.files[index]) {
|
|
53
49
|
state.files[index].status = 'complete';
|
|
54
50
|
state.files[index].file = file;
|
|
51
|
+
// Reflect completion in the aggregate even if the final progress event was throttled.
|
|
52
|
+
state.files[index].uploadedBytes = state.files[index].size;
|
|
55
53
|
}
|
|
56
|
-
state.progress = computeProgress(state.files);
|
|
57
54
|
},
|
|
58
55
|
setFileError (state, action) {
|
|
59
56
|
const { index, name, message } = action.payload;
|
|
@@ -68,10 +65,6 @@ const uploadProgressSlice = createSlice({
|
|
|
68
65
|
message
|
|
69
66
|
}
|
|
70
67
|
];
|
|
71
|
-
state.progress = computeProgress(state.files);
|
|
72
|
-
},
|
|
73
|
-
updateProgress (state, action) {
|
|
74
|
-
state.progress = action.payload;
|
|
75
68
|
},
|
|
76
69
|
addUploadErrors (state, action) {
|
|
77
70
|
state.errors = [
|
|
@@ -82,7 +75,6 @@ const uploadProgressSlice = createSlice({
|
|
|
82
75
|
closeUploadProgress (state) {
|
|
83
76
|
state.isVisible = false;
|
|
84
77
|
state.isMinimized = false;
|
|
85
|
-
state.progress = 0;
|
|
86
78
|
state.totalFiles = 0;
|
|
87
79
|
state.files = [];
|
|
88
80
|
state.errors = [];
|
|
@@ -101,7 +93,6 @@ const uploadProgressSlice = createSlice({
|
|
|
101
93
|
}
|
|
102
94
|
return file;
|
|
103
95
|
});
|
|
104
|
-
state.progress = computeProgress(state.files);
|
|
105
96
|
},
|
|
106
97
|
setUploadFailed (state, action) {
|
|
107
98
|
// Mark all pending and uploading files as errored when a catastrophic failure occurs
|
|
@@ -115,7 +106,6 @@ const uploadProgressSlice = createSlice({
|
|
|
115
106
|
}
|
|
116
107
|
return file;
|
|
117
108
|
});
|
|
118
|
-
state.progress = 100;
|
|
119
109
|
state.errors = [
|
|
120
110
|
...state.errors,
|
|
121
111
|
{
|
|
@@ -130,17 +120,32 @@ const uploadProgressSlice = createSlice({
|
|
|
130
120
|
if (file.status === 'cancelled') {
|
|
131
121
|
return {
|
|
132
122
|
...file,
|
|
133
|
-
status: 'pending'
|
|
123
|
+
status: 'pending',
|
|
124
|
+
uploadedBytes: 0
|
|
134
125
|
};
|
|
135
126
|
}
|
|
136
127
|
return file;
|
|
137
128
|
});
|
|
138
|
-
state.progress = computeProgress(state.files);
|
|
139
129
|
}
|
|
140
130
|
}
|
|
141
131
|
});
|
|
142
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Byte-weighted aggregate progress across the whole batch: `sum(uploadedBytes) / sum(size)`.
|
|
134
|
+
*
|
|
135
|
+
* Falls back to count-based progress (settled files / total files) when all sizes are
|
|
136
|
+
* zero — e.g. URL-flow rows where the file size is unknown up front.
|
|
137
|
+
*/ const selectAggregateProgress = createSelector((state)=>state.uploadProgress.files, (files)=>{
|
|
138
|
+
if (files.length === 0) return 0;
|
|
139
|
+
const totalSize = files.reduce((sum, f)=>sum + f.size, 0);
|
|
140
|
+
if (totalSize === 0) {
|
|
141
|
+
const settled = files.filter((f)=>f.status === 'complete' || f.status === 'error' || f.status === 'cancelled').length;
|
|
142
|
+
return Math.round(settled / files.length * 100);
|
|
143
|
+
}
|
|
144
|
+
const uploadedBytes = files.reduce((sum, f)=>sum + f.uploadedBytes, 0);
|
|
145
|
+
return Math.round(uploadedBytes / totalSize * 100);
|
|
146
|
+
});
|
|
147
|
+
const { openUploadProgress, setFileUploading, setFileProgress, setFileComplete, setFileError, addUploadErrors, closeUploadProgress, toggleMinimize, cancelUpload, setUploadFailed, retryCancelledFiles } = uploadProgressSlice.actions;
|
|
143
148
|
const uploadProgressReducer = uploadProgressSlice.reducer;
|
|
144
149
|
|
|
145
|
-
export { addUploadErrors, cancelUpload, closeUploadProgress, openUploadProgress, retryCancelledFiles, setFileComplete, setFileError, setFileUploading, setUploadFailed, toggleMinimize,
|
|
150
|
+
export { addUploadErrors, cancelUpload, closeUploadProgress, openUploadProgress, retryCancelledFiles, selectAggregateProgress, setFileComplete, setFileError, setFileProgress, setFileUploading, setUploadFailed, toggleMinimize, uploadProgressReducer };
|
|
146
151
|
//# sourceMappingURL=uploadProgress.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadProgress.mjs","sources":["../../../../admin/src/future/store/uploadProgress.ts"],"sourcesContent":["import { createSlice, type PayloadAction } from '@reduxjs/toolkit';\n\nimport type { File } from '../../../../shared/contracts/files';\n\nexport interface FileUploadError {\n name: string;\n message: string;\n}\n\nexport type FileProgressStatus = 'pending' | 'uploading' | 'complete' | 'error' | 'cancelled';\n\nexport interface FileProgress {\n name: string;\n index: number;\n status: FileProgressStatus;\n size: number;\n file?: File;\n error?: string;\n}\n\nexport interface UploadProgressState {\n isVisible: boolean;\n isMinimized: boolean;\n progress: number;\n totalFiles: number;\n files: FileProgress[];\n errors: FileUploadError[];\n uploadId: number;\n}\n\nexport interface RootState {\n uploadProgress: UploadProgressState;\n}\n\nconst initialState: UploadProgressState = {\n isVisible: false,\n isMinimized: false,\n progress: 0,\n totalFiles: 0,\n files: [],\n errors: [],\n uploadId: 0,\n};\n\nconst computeProgress = (files: FileProgress[]): number => {\n if (files.length === 0) return 0;\n const totalSize = files.reduce((sum, f) => sum + f.size, 0);\n if (totalSize === 0) {\n // Fallback to count-based if sizes are unknown\n const completed = files.filter(\n (f) => f.status === 'complete' || f.status === 'error' || f.status === 'cancelled'\n ).length;\n return Math.round((completed / files.length) * 100);\n }\n const completedSize = files\n .filter((f) => f.status === 'complete' || f.status === 'error' || f.status === 'cancelled')\n .reduce((sum, f) => sum + f.size, 0);\n return Math.round((completedSize / totalSize) * 100);\n};\n\nconst uploadProgressSlice = createSlice({\n name: 'uploadProgress',\n initialState,\n reducers: {\n openUploadProgress(\n state,\n action: PayloadAction<{\n totalFiles: number;\n fileNames: string[];\n fileSizes?: number[];\n }>\n ) {\n state.isVisible = true;\n state.isMinimized = false;\n state.progress = 0;\n\n // Create pending files for upload\n const pendingFiles: FileProgress[] = action.payload.fileNames.map((name, index) => ({\n name,\n index,\n status: 'pending' as FileProgressStatus,\n size: action.payload.fileSizes?.[index] ?? 0,\n }));\n\n state.files = pendingFiles;\n state.totalFiles = action.payload.totalFiles;\n state.errors = [];\n state.uploadId += 1;\n },\n setFileUploading(\n state,\n action: PayloadAction<{ name: string; index: number; total: number; size: number }>\n ) {\n const { index, size } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'uploading';\n state.files[index].size = size;\n }\n },\n setFileComplete(state, action: PayloadAction<{ index: number; file: File }>) {\n const { index, file } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'complete';\n state.files[index].file = file;\n }\n state.progress = computeProgress(state.files);\n },\n setFileError(state, action: PayloadAction<{ index: number; name: string; message: string }>) {\n const { index, name, message } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'error';\n state.files[index].error = message;\n }\n state.errors = [...state.errors, { name, message }];\n state.progress = computeProgress(state.files);\n },\n updateProgress(state, action: PayloadAction<number>) {\n state.progress = action.payload;\n },\n addUploadErrors(state, action: PayloadAction<FileUploadError[]>) {\n state.errors = [...state.errors, ...action.payload];\n },\n closeUploadProgress(state) {\n state.isVisible = false;\n state.isMinimized = false;\n state.progress = 0;\n state.totalFiles = 0;\n state.files = [];\n state.errors = [];\n },\n toggleMinimize(state) {\n state.isMinimized = !state.isMinimized;\n },\n cancelUpload(state) {\n // Mark all pending and uploading files as cancelled\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return { ...file, status: 'cancelled' as FileProgressStatus };\n }\n return file;\n });\n state.progress = computeProgress(state.files);\n },\n setUploadFailed(state, action: PayloadAction<{ message: string }>) {\n // Mark all pending and uploading files as errored when a catastrophic failure occurs\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return {\n ...file,\n status: 'error' as FileProgressStatus,\n error: action.payload.message,\n };\n }\n return file;\n });\n state.progress = 100;\n state.errors = [...state.errors, { name: 'Upload Error', message: action.payload.message }];\n },\n retryCancelledFiles(state) {\n // Reset all cancelled files back to pending for retry\n state.files = state.files.map((file) => {\n if (file.status === 'cancelled') {\n return {\n ...file,\n status: 'pending' as FileProgressStatus,\n };\n }\n return file;\n });\n state.progress = computeProgress(state.files);\n },\n },\n});\n\nexport const {\n openUploadProgress,\n setFileUploading,\n setFileComplete,\n setFileError,\n updateProgress,\n addUploadErrors,\n closeUploadProgress,\n toggleMinimize,\n cancelUpload,\n setUploadFailed,\n retryCancelledFiles,\n} = uploadProgressSlice.actions;\n\nexport const uploadProgressReducer = uploadProgressSlice.reducer;\n"],"names":["initialState","isVisible","isMinimized","progress","totalFiles","files","errors","uploadId","computeProgress","length","totalSize","reduce","sum","f","size","completed","filter","status","Math","round","completedSize","uploadProgressSlice","createSlice","name","reducers","openUploadProgress","state","action","pendingFiles","payload","fileNames","map","index","fileSizes","setFileUploading","setFileComplete","file","setFileError","message","error","updateProgress","addUploadErrors","closeUploadProgress","toggleMinimize","cancelUpload","setUploadFailed","retryCancelledFiles","actions","uploadProgressReducer","reducer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"uploadProgress.mjs","sources":["../../../../admin/src/future/store/uploadProgress.ts"],"sourcesContent":["import { createSelector, createSlice, type PayloadAction } from '@reduxjs/toolkit';\n\nimport type { File } from '../../../../shared/contracts/files';\n\nexport interface FileUploadError {\n name: string;\n message: string;\n}\n\nexport type FileProgressStatus = 'pending' | 'uploading' | 'complete' | 'error' | 'cancelled';\n\nexport interface FileProgress {\n name: string;\n index: number;\n status: FileProgressStatus;\n size: number;\n uploadedBytes: number;\n file?: File;\n error?: string;\n}\n\nexport interface UploadProgressState {\n isVisible: boolean;\n isMinimized: boolean;\n totalFiles: number;\n files: FileProgress[];\n errors: FileUploadError[];\n uploadId: number;\n}\n\nexport interface RootState {\n uploadProgress: UploadProgressState;\n}\n\nconst initialState: UploadProgressState = {\n isVisible: false,\n isMinimized: false,\n totalFiles: 0,\n files: [],\n errors: [],\n uploadId: 0,\n};\n\nconst uploadProgressSlice = createSlice({\n name: 'uploadProgress',\n initialState,\n reducers: {\n openUploadProgress(\n state,\n action: PayloadAction<{\n totalFiles: number;\n fileNames: string[];\n fileSizes?: number[];\n }>\n ) {\n state.isVisible = true;\n state.isMinimized = false;\n\n // Create pending files for upload\n const pendingFiles: FileProgress[] = action.payload.fileNames.map((name, index) => ({\n name,\n index,\n status: 'pending' as FileProgressStatus,\n size: action.payload.fileSizes?.[index] ?? 0,\n uploadedBytes: 0,\n }));\n\n state.files = pendingFiles;\n state.totalFiles = action.payload.totalFiles;\n state.errors = [];\n state.uploadId += 1;\n },\n setFileUploading(state, action: PayloadAction<{ name: string; index: number; size: number }>) {\n const { index, size } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'uploading';\n state.files[index].size = size;\n }\n },\n setFileProgress(state, action: PayloadAction<{ index: number; bytes: number }>) {\n const { index, bytes } = action.payload;\n const file = state.files[index];\n if (file) {\n // Clamp to the known file size so the aggregate can never exceed 100%.\n file.uploadedBytes = Math.min(bytes, file.size);\n }\n },\n setFileComplete(state, action: PayloadAction<{ index: number; file: File }>) {\n const { index, file } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'complete';\n state.files[index].file = file;\n // Reflect completion in the aggregate even if the final progress event was throttled.\n state.files[index].uploadedBytes = state.files[index].size;\n }\n },\n setFileError(state, action: PayloadAction<{ index: number; name: string; message: string }>) {\n const { index, name, message } = action.payload;\n if (state.files[index]) {\n state.files[index].status = 'error';\n state.files[index].error = message;\n }\n state.errors = [...state.errors, { name, message }];\n },\n addUploadErrors(state, action: PayloadAction<FileUploadError[]>) {\n state.errors = [...state.errors, ...action.payload];\n },\n closeUploadProgress(state) {\n state.isVisible = false;\n state.isMinimized = false;\n state.totalFiles = 0;\n state.files = [];\n state.errors = [];\n },\n toggleMinimize(state) {\n state.isMinimized = !state.isMinimized;\n },\n cancelUpload(state) {\n // Mark all pending and uploading files as cancelled\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return { ...file, status: 'cancelled' as FileProgressStatus };\n }\n return file;\n });\n },\n setUploadFailed(state, action: PayloadAction<{ message: string }>) {\n // Mark all pending and uploading files as errored when a catastrophic failure occurs\n state.files = state.files.map((file) => {\n if (file.status === 'pending' || file.status === 'uploading') {\n return {\n ...file,\n status: 'error' as FileProgressStatus,\n error: action.payload.message,\n };\n }\n return file;\n });\n state.errors = [...state.errors, { name: 'Upload Error', message: action.payload.message }];\n },\n retryCancelledFiles(state) {\n // Reset all cancelled files back to pending for retry\n state.files = state.files.map((file) => {\n if (file.status === 'cancelled') {\n return {\n ...file,\n status: 'pending' as FileProgressStatus,\n uploadedBytes: 0,\n };\n }\n return file;\n });\n },\n },\n});\n\n/**\n * Byte-weighted aggregate progress across the whole batch: `sum(uploadedBytes) / sum(size)`.\n *\n * Falls back to count-based progress (settled files / total files) when all sizes are\n * zero — e.g. URL-flow rows where the file size is unknown up front.\n */\nexport const selectAggregateProgress = createSelector(\n (state: RootState) => state.uploadProgress.files,\n (files): number => {\n if (files.length === 0) return 0;\n\n const totalSize = files.reduce((sum, f) => sum + f.size, 0);\n\n if (totalSize === 0) {\n const settled = files.filter(\n (f) => f.status === 'complete' || f.status === 'error' || f.status === 'cancelled'\n ).length;\n return Math.round((settled / files.length) * 100);\n }\n\n const uploadedBytes = files.reduce((sum, f) => sum + f.uploadedBytes, 0);\n return Math.round((uploadedBytes / totalSize) * 100);\n }\n);\n\nexport const {\n openUploadProgress,\n setFileUploading,\n setFileProgress,\n setFileComplete,\n setFileError,\n addUploadErrors,\n closeUploadProgress,\n toggleMinimize,\n cancelUpload,\n setUploadFailed,\n retryCancelledFiles,\n} = uploadProgressSlice.actions;\n\nexport const uploadProgressReducer = uploadProgressSlice.reducer;\n"],"names":["initialState","isVisible","isMinimized","totalFiles","files","errors","uploadId","uploadProgressSlice","createSlice","name","reducers","openUploadProgress","state","action","pendingFiles","payload","fileNames","map","index","status","size","fileSizes","uploadedBytes","setFileUploading","setFileProgress","bytes","file","Math","min","setFileComplete","setFileError","message","error","addUploadErrors","closeUploadProgress","toggleMinimize","cancelUpload","setUploadFailed","retryCancelledFiles","selectAggregateProgress","createSelector","uploadProgress","length","totalSize","reduce","sum","f","settled","filter","round","actions","uploadProgressReducer","reducer"],"mappings":";;AAkCA,MAAMA,YAAAA,GAAoC;IACxCC,SAAAA,EAAW,KAAA;IACXC,WAAAA,EAAa,KAAA;IACbC,UAAAA,EAAY,CAAA;AACZC,IAAAA,KAAAA,EAAO,EAAE;AACTC,IAAAA,MAAAA,EAAQ,EAAE;IACVC,QAAAA,EAAU;AACZ,CAAA;AAEA,MAAMC,sBAAsBC,WAAAA,CAAY;IACtCC,IAAAA,EAAM,gBAAA;AACNT,IAAAA,YAAAA;IACAU,QAAAA,EAAU;QACRC,kBAAAA,CAAAA,CACEC,KAAK,EACLC,MAIE,EAAA;AAEFD,YAAAA,KAAAA,CAAMX,SAAS,GAAG,IAAA;AAClBW,YAAAA,KAAAA,CAAMV,WAAW,GAAG,KAAA;;YAGpB,MAAMY,YAAAA,GAA+BD,MAAAA,CAAOE,OAAO,CAACC,SAAS,CAACC,GAAG,CAAC,CAACR,IAAAA,EAAMS,KAAAA,IAAW;AAClFT,oBAAAA,IAAAA;AACAS,oBAAAA,KAAAA;oBACAC,MAAAA,EAAQ,SAAA;AACRC,oBAAAA,IAAAA,EAAMP,OAAOE,OAAO,CAACM,SAAS,GAAGH,MAAM,IAAI,CAAA;oBAC3CI,aAAAA,EAAe;iBACjB,CAAA,CAAA;AAEAV,YAAAA,KAAAA,CAAMR,KAAK,GAAGU,YAAAA;AACdF,YAAAA,KAAAA,CAAMT,UAAU,GAAGU,MAAAA,CAAOE,OAAO,CAACZ,UAAU;YAC5CS,KAAAA,CAAMP,MAAM,GAAG,EAAE;AACjBO,YAAAA,KAAAA,CAAMN,QAAQ,IAAI,CAAA;AACpB,QAAA,CAAA;QACAiB,gBAAAA,CAAAA,CAAiBX,KAAK,EAAEC,MAAoE,EAAA;AAC1F,YAAA,MAAM,EAAEK,KAAK,EAAEE,IAAI,EAAE,GAAGP,OAAOE,OAAO;AACtC,YAAA,IAAIH,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,EAAE;AACtBN,gBAAAA,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACC,MAAM,GAAG,WAAA;AAC5BP,gBAAAA,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACE,IAAI,GAAGA,IAAAA;AAC5B,YAAA;AACF,QAAA,CAAA;QACAI,eAAAA,CAAAA,CAAgBZ,KAAK,EAAEC,MAAuD,EAAA;AAC5E,YAAA,MAAM,EAAEK,KAAK,EAAEO,KAAK,EAAE,GAAGZ,OAAOE,OAAO;AACvC,YAAA,MAAMW,IAAAA,GAAOd,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM;AAC/B,YAAA,IAAIQ,IAAAA,EAAM;;AAERA,gBAAAA,IAAAA,CAAKJ,aAAa,GAAGK,IAAAA,CAAKC,GAAG,CAACH,KAAAA,EAAOC,KAAKN,IAAI,CAAA;AAChD,YAAA;AACF,QAAA,CAAA;QACAS,eAAAA,CAAAA,CAAgBjB,KAAK,EAAEC,MAAoD,EAAA;AACzE,YAAA,MAAM,EAAEK,KAAK,EAAEQ,IAAI,EAAE,GAAGb,OAAOE,OAAO;AACtC,YAAA,IAAIH,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,EAAE;AACtBN,gBAAAA,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACC,MAAM,GAAG,UAAA;AAC5BP,gBAAAA,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACQ,IAAI,GAAGA,IAAAA;;gBAE1Bd,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACI,aAAa,GAAGV,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACE,IAAI;AAC5D,YAAA;AACF,QAAA,CAAA;QACAU,YAAAA,CAAAA,CAAalB,KAAK,EAAEC,MAAuE,EAAA;YACzF,MAAM,EAAEK,KAAK,EAAET,IAAI,EAAEsB,OAAO,EAAE,GAAGlB,MAAAA,CAAOE,OAAO;AAC/C,YAAA,IAAIH,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,EAAE;AACtBN,gBAAAA,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACC,MAAM,GAAG,OAAA;AAC5BP,gBAAAA,KAAAA,CAAMR,KAAK,CAACc,KAAAA,CAAM,CAACc,KAAK,GAAGD,OAAAA;AAC7B,YAAA;AACAnB,YAAAA,KAAAA,CAAMP,MAAM,GAAG;AAAIO,gBAAAA,GAAAA,KAAAA,CAAMP,MAAM;AAAE,gBAAA;AAAEI,oBAAAA,IAAAA;AAAMsB,oBAAAA;AAAQ;AAAE,aAAA;AACrD,QAAA,CAAA;QACAE,eAAAA,CAAAA,CAAgBrB,KAAK,EAAEC,MAAwC,EAAA;AAC7DD,YAAAA,KAAAA,CAAMP,MAAM,GAAG;AAAIO,gBAAAA,GAAAA,KAAAA,CAAMP,MAAM;AAAKQ,gBAAAA,GAAAA,MAAAA,CAAOE;AAAQ,aAAA;AACrD,QAAA,CAAA;AACAmB,QAAAA,mBAAAA,CAAAA,CAAoBtB,KAAK,EAAA;AACvBA,YAAAA,KAAAA,CAAMX,SAAS,GAAG,KAAA;AAClBW,YAAAA,KAAAA,CAAMV,WAAW,GAAG,KAAA;AACpBU,YAAAA,KAAAA,CAAMT,UAAU,GAAG,CAAA;YACnBS,KAAAA,CAAMR,KAAK,GAAG,EAAE;YAChBQ,KAAAA,CAAMP,MAAM,GAAG,EAAE;AACnB,QAAA,CAAA;AACA8B,QAAAA,cAAAA,CAAAA,CAAevB,KAAK,EAAA;AAClBA,YAAAA,KAAAA,CAAMV,WAAW,GAAG,CAACU,KAAAA,CAAMV,WAAW;AACxC,QAAA,CAAA;AACAkC,QAAAA,YAAAA,CAAAA,CAAaxB,KAAK,EAAA;;AAEhBA,YAAAA,KAAAA,CAAMR,KAAK,GAAGQ,KAAAA,CAAMR,KAAK,CAACa,GAAG,CAAC,CAACS,IAAAA,GAAAA;AAC7B,gBAAA,IAAIA,KAAKP,MAAM,KAAK,aAAaO,IAAAA,CAAKP,MAAM,KAAK,WAAA,EAAa;oBAC5D,OAAO;AAAE,wBAAA,GAAGO,IAAI;wBAAEP,MAAAA,EAAQ;AAAkC,qBAAA;AAC9D,gBAAA;gBACA,OAAOO,IAAAA;AACT,YAAA,CAAA,CAAA;AACF,QAAA,CAAA;QACAW,eAAAA,CAAAA,CAAgBzB,KAAK,EAAEC,MAA0C,EAAA;;AAE/DD,YAAAA,KAAAA,CAAMR,KAAK,GAAGQ,KAAAA,CAAMR,KAAK,CAACa,GAAG,CAAC,CAACS,IAAAA,GAAAA;AAC7B,gBAAA,IAAIA,KAAKP,MAAM,KAAK,aAAaO,IAAAA,CAAKP,MAAM,KAAK,WAAA,EAAa;oBAC5D,OAAO;AACL,wBAAA,GAAGO,IAAI;wBACPP,MAAAA,EAAQ,OAAA;wBACRa,KAAAA,EAAOnB,MAAAA,CAAOE,OAAO,CAACgB;AACxB,qBAAA;AACF,gBAAA;gBACA,OAAOL,IAAAA;AACT,YAAA,CAAA,CAAA;AACAd,YAAAA,KAAAA,CAAMP,MAAM,GAAG;AAAIO,gBAAAA,GAAAA,KAAAA,CAAMP,MAAM;AAAE,gBAAA;oBAAEI,IAAAA,EAAM,cAAA;oBAAgBsB,OAAAA,EAASlB,MAAAA,CAAOE,OAAO,CAACgB;AAAQ;AAAE,aAAA;AAC7F,QAAA,CAAA;AACAO,QAAAA,mBAAAA,CAAAA,CAAoB1B,KAAK,EAAA;;AAEvBA,YAAAA,KAAAA,CAAMR,KAAK,GAAGQ,KAAAA,CAAMR,KAAK,CAACa,GAAG,CAAC,CAACS,IAAAA,GAAAA;gBAC7B,IAAIA,IAAAA,CAAKP,MAAM,KAAK,WAAA,EAAa;oBAC/B,OAAO;AACL,wBAAA,GAAGO,IAAI;wBACPP,MAAAA,EAAQ,SAAA;wBACRG,aAAAA,EAAe;AACjB,qBAAA;AACF,gBAAA;gBACA,OAAOI,IAAAA;AACT,YAAA,CAAA,CAAA;AACF,QAAA;AACF;AACF,CAAA,CAAA;AAEA;;;;;IAMO,MAAMa,uBAAAA,GAA0BC,cAAAA,CACrC,CAAC5B,KAAAA,GAAqBA,KAAAA,CAAM6B,cAAc,CAACrC,KAAK,EAChD,CAACA,KAAAA,GAAAA;AACC,IAAA,IAAIA,KAAAA,CAAMsC,MAAM,KAAK,CAAA,EAAG,OAAO,CAAA;IAE/B,MAAMC,SAAAA,GAAYvC,KAAAA,CAAMwC,MAAM,CAAC,CAACC,KAAKC,CAAAA,GAAMD,GAAAA,GAAMC,CAAAA,CAAE1B,IAAI,EAAE,CAAA,CAAA;AAEzD,IAAA,IAAIuB,cAAc,CAAA,EAAG;AACnB,QAAA,MAAMI,UAAU3C,KAAAA,CAAM4C,MAAM,CAC1B,CAACF,CAAAA,GAAMA,EAAE3B,MAAM,KAAK,UAAA,IAAc2B,CAAAA,CAAE3B,MAAM,KAAK,OAAA,IAAW2B,EAAE3B,MAAM,KAAK,aACvEuB,MAAM;AACR,QAAA,OAAOf,KAAKsB,KAAK,CAAC,OAACF,GAAU3C,KAAAA,CAAMsC,MAAM,GAAI,GAAA,CAAA;AAC/C,IAAA;IAEA,MAAMpB,aAAAA,GAAgBlB,KAAAA,CAAMwC,MAAM,CAAC,CAACC,KAAKC,CAAAA,GAAMD,GAAAA,GAAMC,CAAAA,CAAExB,aAAa,EAAE,CAAA,CAAA;AACtE,IAAA,OAAOK,IAAAA,CAAKsB,KAAK,CAAE3B,gBAAgBqB,SAAAA,GAAa,GAAA,CAAA;AAClD,CAAA;AAGK,MAAM,EACXhC,kBAAkB,EAClBY,gBAAgB,EAChBC,eAAe,EACfK,eAAe,EACfC,YAAY,EACZG,eAAe,EACfC,mBAAmB,EACnBC,cAAc,EACdC,YAAY,EACZC,eAAe,EACfC,mBAAmB,EACpB,GAAG/B,mBAAAA,CAAoB2C;AAEjB,MAAMC,qBAAAA,GAAwB5C,mBAAAA,CAAoB6C;;;;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Coalesces high-frequency values into at most one flush per animation frame.
|
|
5
|
+
*
|
|
6
|
+
* `XHR.upload.onprogress` can fire many times per second on a fast connection.
|
|
7
|
+
* Dispatching each one to Redux would flood the store, so the orchestrator routes
|
|
8
|
+
* progress through a batcher: many `schedule(value)` calls within a single frame
|
|
9
|
+
* collapse into one `flush(latestValue)` callback.
|
|
10
|
+
*
|
|
11
|
+
* @param flush - Invoked once per frame with the most recent scheduled value.
|
|
12
|
+
*/ const createRafBatcher = (flush)=>{
|
|
13
|
+
let frame = null;
|
|
14
|
+
let latest;
|
|
15
|
+
const run = ()=>{
|
|
16
|
+
frame = null;
|
|
17
|
+
flush(latest);
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
/**
|
|
21
|
+
* Records the latest value and ensures a flush is scheduled for the next frame.
|
|
22
|
+
* Repeated calls within the same frame overwrite the value without scheduling
|
|
23
|
+
* additional frames.
|
|
24
|
+
*/ schedule (value) {
|
|
25
|
+
latest = value;
|
|
26
|
+
if (frame === null) {
|
|
27
|
+
frame = requestAnimationFrame(run);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* Cancels any pending flush so a value scheduled this frame will not fire.
|
|
32
|
+
*/ cancel () {
|
|
33
|
+
if (frame !== null) {
|
|
34
|
+
cancelAnimationFrame(frame);
|
|
35
|
+
frame = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
exports.createRafBatcher = createRafBatcher;
|
|
42
|
+
//# sourceMappingURL=createRafBatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createRafBatcher.js","sources":["../../../../admin/src/future/utils/createRafBatcher.ts"],"sourcesContent":["/**\n * Coalesces high-frequency values into at most one flush per animation frame.\n *\n * `XHR.upload.onprogress` can fire many times per second on a fast connection.\n * Dispatching each one to Redux would flood the store, so the orchestrator routes\n * progress through a batcher: many `schedule(value)` calls within a single frame\n * collapse into one `flush(latestValue)` callback.\n *\n * @param flush - Invoked once per frame with the most recent scheduled value.\n */\nexport const createRafBatcher = <T>(flush: (value: T) => void) => {\n let frame: number | null = null;\n let latest: T;\n\n const run = () => {\n frame = null;\n flush(latest);\n };\n\n return {\n /**\n * Records the latest value and ensures a flush is scheduled for the next frame.\n * Repeated calls within the same frame overwrite the value without scheduling\n * additional frames.\n */\n schedule(value: T) {\n latest = value;\n if (frame === null) {\n frame = requestAnimationFrame(run);\n }\n },\n /**\n * Cancels any pending flush so a value scheduled this frame will not fire.\n */\n cancel() {\n if (frame !== null) {\n cancelAnimationFrame(frame);\n frame = null;\n }\n },\n };\n};\n\nexport type RafBatcher<T> = ReturnType<typeof createRafBatcher<T>>;\n"],"names":["createRafBatcher","flush","frame","latest","run","schedule","value","requestAnimationFrame","cancel","cancelAnimationFrame"],"mappings":";;AAAA;;;;;;;;;IAUO,MAAMA,gBAAAA,GAAmB,CAAIC,KAAAA,GAAAA;AAClC,IAAA,IAAIC,KAAAA,GAAuB,IAAA;IAC3B,IAAIC,MAAAA;AAEJ,IAAA,MAAMC,GAAAA,GAAM,IAAA;QACVF,KAAAA,GAAQ,IAAA;QACRD,KAAAA,CAAME,MAAAA,CAAAA;AACR,IAAA,CAAA;IAEA,OAAO;AACL;;;;AAIC,QACDE,UAASC,KAAQ,EAAA;YACfH,MAAAA,GAASG,KAAAA;AACT,YAAA,IAAIJ,UAAU,IAAA,EAAM;AAClBA,gBAAAA,KAAAA,GAAQK,qBAAAA,CAAsBH,GAAAA,CAAAA;AAChC,YAAA;AACF,QAAA,CAAA;AACA;;QAGAI,MAAAA,CAAAA,GAAAA;AACE,YAAA,IAAIN,UAAU,IAAA,EAAM;gBAClBO,oBAAAA,CAAqBP,KAAAA,CAAAA;gBACrBA,KAAAA,GAAQ,IAAA;AACV,YAAA;AACF,QAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coalesces high-frequency values into at most one flush per animation frame.
|
|
3
|
+
*
|
|
4
|
+
* `XHR.upload.onprogress` can fire many times per second on a fast connection.
|
|
5
|
+
* Dispatching each one to Redux would flood the store, so the orchestrator routes
|
|
6
|
+
* progress through a batcher: many `schedule(value)` calls within a single frame
|
|
7
|
+
* collapse into one `flush(latestValue)` callback.
|
|
8
|
+
*
|
|
9
|
+
* @param flush - Invoked once per frame with the most recent scheduled value.
|
|
10
|
+
*/ const createRafBatcher = (flush)=>{
|
|
11
|
+
let frame = null;
|
|
12
|
+
let latest;
|
|
13
|
+
const run = ()=>{
|
|
14
|
+
frame = null;
|
|
15
|
+
flush(latest);
|
|
16
|
+
};
|
|
17
|
+
return {
|
|
18
|
+
/**
|
|
19
|
+
* Records the latest value and ensures a flush is scheduled for the next frame.
|
|
20
|
+
* Repeated calls within the same frame overwrite the value without scheduling
|
|
21
|
+
* additional frames.
|
|
22
|
+
*/ schedule (value) {
|
|
23
|
+
latest = value;
|
|
24
|
+
if (frame === null) {
|
|
25
|
+
frame = requestAnimationFrame(run);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* Cancels any pending flush so a value scheduled this frame will not fire.
|
|
30
|
+
*/ cancel () {
|
|
31
|
+
if (frame !== null) {
|
|
32
|
+
cancelAnimationFrame(frame);
|
|
33
|
+
frame = null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { createRafBatcher };
|
|
40
|
+
//# sourceMappingURL=createRafBatcher.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createRafBatcher.mjs","sources":["../../../../admin/src/future/utils/createRafBatcher.ts"],"sourcesContent":["/**\n * Coalesces high-frequency values into at most one flush per animation frame.\n *\n * `XHR.upload.onprogress` can fire many times per second on a fast connection.\n * Dispatching each one to Redux would flood the store, so the orchestrator routes\n * progress through a batcher: many `schedule(value)` calls within a single frame\n * collapse into one `flush(latestValue)` callback.\n *\n * @param flush - Invoked once per frame with the most recent scheduled value.\n */\nexport const createRafBatcher = <T>(flush: (value: T) => void) => {\n let frame: number | null = null;\n let latest: T;\n\n const run = () => {\n frame = null;\n flush(latest);\n };\n\n return {\n /**\n * Records the latest value and ensures a flush is scheduled for the next frame.\n * Repeated calls within the same frame overwrite the value without scheduling\n * additional frames.\n */\n schedule(value: T) {\n latest = value;\n if (frame === null) {\n frame = requestAnimationFrame(run);\n }\n },\n /**\n * Cancels any pending flush so a value scheduled this frame will not fire.\n */\n cancel() {\n if (frame !== null) {\n cancelAnimationFrame(frame);\n frame = null;\n }\n },\n };\n};\n\nexport type RafBatcher<T> = ReturnType<typeof createRafBatcher<T>>;\n"],"names":["createRafBatcher","flush","frame","latest","run","schedule","value","requestAnimationFrame","cancel","cancelAnimationFrame"],"mappings":"AAAA;;;;;;;;;IAUO,MAAMA,gBAAAA,GAAmB,CAAIC,KAAAA,GAAAA;AAClC,IAAA,IAAIC,KAAAA,GAAuB,IAAA;IAC3B,IAAIC,MAAAA;AAEJ,IAAA,MAAMC,GAAAA,GAAM,IAAA;QACVF,KAAAA,GAAQ,IAAA;QACRD,KAAAA,CAAME,MAAAA,CAAAA;AACR,IAAA,CAAA;IAEA,OAAO;AACL;;;;AAIC,QACDE,UAASC,KAAQ,EAAA;YACfH,MAAAA,GAASG,KAAAA;AACT,YAAA,IAAIJ,UAAU,IAAA,EAAM;AAClBA,gBAAAA,KAAAA,GAAQK,qBAAAA,CAAsBH,GAAAA,CAAAA;AAChC,YAAA;AACF,QAAA,CAAA;AACA;;QAGAI,MAAAA,CAAAA,GAAAA;AACE,YAAA,IAAIN,UAAU,IAAA,EAAM;gBAClBO,oBAAAA,CAAqBP,KAAAA,CAAAA;gBACrBA,KAAAA,GAAQ,IAAA;AACV,YAAA;AACF,QAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fetch a file at `url` and trigger a browser download with the given filename.
|
|
5
|
+
* Goes via a blob + temporary anchor so we honour the `download` attribute
|
|
6
|
+
* even when the file is served same-origin without `Content-Disposition`.
|
|
7
|
+
*/ const downloadFile = async (url, fileName)=>{
|
|
8
|
+
const response = await fetch(url);
|
|
9
|
+
const blob = await response.blob();
|
|
10
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
11
|
+
const anchor = document.createElement('a');
|
|
12
|
+
anchor.href = objectUrl;
|
|
13
|
+
anchor.setAttribute('download', fileName);
|
|
14
|
+
anchor.click();
|
|
15
|
+
window.URL.revokeObjectURL(objectUrl);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
exports.downloadFile = downloadFile;
|
|
19
|
+
//# sourceMappingURL=downloadFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloadFile.js","sources":["../../../../admin/src/future/utils/downloadFile.ts"],"sourcesContent":["/**\n * Fetch a file at `url` and trigger a browser download with the given filename.\n * Goes via a blob + temporary anchor so we honour the `download` attribute\n * even when the file is served same-origin without `Content-Disposition`.\n */\nexport const downloadFile = async (url: string, fileName: string) => {\n const response = await fetch(url);\n const blob = await response.blob();\n const objectUrl = window.URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = objectUrl;\n anchor.setAttribute('download', fileName);\n anchor.click();\n window.URL.revokeObjectURL(objectUrl);\n};\n"],"names":["downloadFile","url","fileName","response","fetch","blob","objectUrl","window","URL","createObjectURL","anchor","document","createElement","href","setAttribute","click","revokeObjectURL"],"mappings":";;AAAA;;;;AAIC,IACM,MAAMA,YAAAA,GAAe,OAAOC,GAAAA,EAAaC,QAAAA,GAAAA;IAC9C,MAAMC,QAAAA,GAAW,MAAMC,KAAAA,CAAMH,GAAAA,CAAAA;IAC7B,MAAMI,IAAAA,GAAO,MAAMF,QAAAA,CAASE,IAAI,EAAA;AAChC,IAAA,MAAMC,SAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAACC,eAAe,CAACJ,IAAAA,CAAAA;IAC7C,MAAMK,MAAAA,GAASC,QAAAA,CAASC,aAAa,CAAC,GAAA,CAAA;AACtCF,IAAAA,MAAAA,CAAOG,IAAI,GAAGP,SAAAA;IACdI,MAAAA,CAAOI,YAAY,CAAC,UAAA,EAAYZ,QAAAA,CAAAA;AAChCQ,IAAAA,MAAAA,CAAOK,KAAK,EAAA;IACZR,MAAAA,CAAOC,GAAG,CAACQ,eAAe,CAACV,SAAAA,CAAAA;AAC7B;;;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch a file at `url` and trigger a browser download with the given filename.
|
|
3
|
+
* Goes via a blob + temporary anchor so we honour the `download` attribute
|
|
4
|
+
* even when the file is served same-origin without `Content-Disposition`.
|
|
5
|
+
*/ const downloadFile = async (url, fileName)=>{
|
|
6
|
+
const response = await fetch(url);
|
|
7
|
+
const blob = await response.blob();
|
|
8
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
9
|
+
const anchor = document.createElement('a');
|
|
10
|
+
anchor.href = objectUrl;
|
|
11
|
+
anchor.setAttribute('download', fileName);
|
|
12
|
+
anchor.click();
|
|
13
|
+
window.URL.revokeObjectURL(objectUrl);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { downloadFile };
|
|
17
|
+
//# sourceMappingURL=downloadFile.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloadFile.mjs","sources":["../../../../admin/src/future/utils/downloadFile.ts"],"sourcesContent":["/**\n * Fetch a file at `url` and trigger a browser download with the given filename.\n * Goes via a blob + temporary anchor so we honour the `download` attribute\n * even when the file is served same-origin without `Content-Disposition`.\n */\nexport const downloadFile = async (url: string, fileName: string) => {\n const response = await fetch(url);\n const blob = await response.blob();\n const objectUrl = window.URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = objectUrl;\n anchor.setAttribute('download', fileName);\n anchor.click();\n window.URL.revokeObjectURL(objectUrl);\n};\n"],"names":["downloadFile","url","fileName","response","fetch","blob","objectUrl","window","URL","createObjectURL","anchor","document","createElement","href","setAttribute","click","revokeObjectURL"],"mappings":"AAAA;;;;AAIC,IACM,MAAMA,YAAAA,GAAe,OAAOC,GAAAA,EAAaC,QAAAA,GAAAA;IAC9C,MAAMC,QAAAA,GAAW,MAAMC,KAAAA,CAAMH,GAAAA,CAAAA;IAC7B,MAAMI,IAAAA,GAAO,MAAMF,QAAAA,CAASE,IAAI,EAAA;AAChC,IAAA,MAAMC,SAAAA,GAAYC,MAAAA,CAAOC,GAAG,CAACC,eAAe,CAACJ,IAAAA,CAAAA;IAC7C,MAAMK,MAAAA,GAASC,QAAAA,CAASC,aAAa,CAAC,GAAA,CAAA;AACtCF,IAAAA,MAAAA,CAAOG,IAAI,GAAGP,SAAAA;IACdI,MAAAA,CAAOI,YAAY,CAAC,UAAA,EAAYZ,QAAAA,CAAAA;AAChCQ,IAAAA,MAAAA,CAAOK,KAAK,EAAA;IACZR,MAAAA,CAAOC,GAAG,CAACQ,eAAe,CAACV,SAAAA,CAAAA;AAC7B;;;;"}
|
|
@@ -31,7 +31,7 @@ const useAssets = ({ skipWhen = false, query = {} } = {})=>{
|
|
|
31
31
|
const { toggleNotification } = strapiAdmin.useNotification();
|
|
32
32
|
const { notifyStatus } = designSystem.useNotifyAT();
|
|
33
33
|
const { get } = strapiAdmin.useFetchClient();
|
|
34
|
-
const { folderPath, _q, ...paramsExceptFolderAndQ } = query;
|
|
34
|
+
const { folder, folderPath: _folderPath, _q, ...paramsExceptFolderAndQ } = query;
|
|
35
35
|
let params;
|
|
36
36
|
if (_q) {
|
|
37
37
|
params = {
|
|
@@ -45,8 +45,10 @@ const useAssets = ({ skipWhen = false, query = {} } = {})=>{
|
|
|
45
45
|
$and: [
|
|
46
46
|
...paramsExceptFolderAndQ?.filters?.$and ?? [],
|
|
47
47
|
{
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
folder: {
|
|
49
|
+
id: folder ?? {
|
|
50
|
+
$null: true
|
|
51
|
+
}
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssets.js","sources":["../../../admin/src/hooks/useAssets.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { useNotification, useFetchClient } from '@strapi/admin/strapi-admin';\nimport { useNotifyAT } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { useQuery } from 'react-query';\n\nimport { Query, GetFiles } from '../../../shared/contracts/files';\nimport { pluginId } from '../pluginId';\n\ninterface UseAssetsOptions {\n skipWhen?: boolean;\n query?: Query;\n}\n\nexport const useAssets = ({ skipWhen = false, query = {} }: UseAssetsOptions = {}) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { notifyStatus } = useNotifyAT();\n const { get } = useFetchClient();\n const { folderPath, _q, ...paramsExceptFolderAndQ } = query;\n\n let params: Query;\n\n if (_q) {\n params = {\n ...paramsExceptFolderAndQ,\n _q: encodeURIComponent(_q),\n };\n } else {\n params = {\n ...paramsExceptFolderAndQ,\n filters: {\n $and: [\n ...(paramsExceptFolderAndQ?.filters?.$and ?? []),\n {\n
|
|
1
|
+
{"version":3,"file":"useAssets.js","sources":["../../../admin/src/hooks/useAssets.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { useNotification, useFetchClient } from '@strapi/admin/strapi-admin';\nimport { useNotifyAT } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { useQuery } from 'react-query';\n\nimport { Query, GetFiles } from '../../../shared/contracts/files';\nimport { pluginId } from '../pluginId';\n\ninterface UseAssetsOptions {\n skipWhen?: boolean;\n query?: Query;\n}\n\nexport const useAssets = ({ skipWhen = false, query = {} }: UseAssetsOptions = {}) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { notifyStatus } = useNotifyAT();\n const { get } = useFetchClient();\n const { folder, folderPath: _folderPath, _q, ...paramsExceptFolderAndQ } = query;\n\n let params: Query;\n\n if (_q) {\n params = {\n ...paramsExceptFolderAndQ,\n _q: encodeURIComponent(_q),\n };\n } else {\n params = {\n ...paramsExceptFolderAndQ,\n filters: {\n $and: [\n ...(paramsExceptFolderAndQ?.filters?.$and ?? []),\n {\n folder: {\n id: folder ?? {\n $null: true,\n },\n },\n },\n ],\n },\n };\n }\n\n const { data, error, isLoading } = useQuery<\n GetFiles.Response['data'],\n GetFiles.Response['error']\n >(\n [pluginId, 'assets', params],\n async () => {\n const { data } = await get('/upload/files', { params });\n\n return data;\n },\n {\n enabled: !skipWhen,\n staleTime: 0,\n cacheTime: 0,\n select(data) {\n if (data?.results && Array.isArray(data.results)) {\n return {\n ...data,\n results: data.results\n /**\n * Filter out assets that don't have a name.\n * So we don't try to render them as assets\n * and get errors.\n */\n .filter((asset) => asset.name)\n .map((asset) => ({\n ...asset,\n /**\n * Mime and ext cannot be null in the front-end because\n * we expect them to be strings and use the `includes` method.\n */\n mime: asset.mime ?? '',\n ext: asset.ext ?? '',\n })),\n };\n }\n\n return data;\n },\n }\n );\n\n React.useEffect(() => {\n if (data) {\n notifyStatus(\n formatMessage({\n id: 'list.asset.at.finished',\n defaultMessage: 'The assets have finished loading.',\n })\n );\n }\n }, [data, formatMessage, notifyStatus]);\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error' }),\n });\n }\n }, [error, formatMessage, toggleNotification]);\n\n return { data, error, isLoading };\n};\n"],"names":["useAssets","skipWhen","query","formatMessage","useIntl","toggleNotification","useNotification","notifyStatus","useNotifyAT","get","useFetchClient","folder","folderPath","_folderPath","_q","paramsExceptFolderAndQ","params","encodeURIComponent","filters","$and","id","$null","data","error","isLoading","useQuery","pluginId","enabled","staleTime","cacheTime","select","results","Array","isArray","filter","asset","name","map","mime","ext","React","useEffect","defaultMessage","type","message"],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ const useAssets = ({ skipWhen = false, query = {} } = {})=>{
|
|
|
10
10
|
const { toggleNotification } = useNotification();
|
|
11
11
|
const { notifyStatus } = useNotifyAT();
|
|
12
12
|
const { get } = useFetchClient();
|
|
13
|
-
const { folderPath, _q, ...paramsExceptFolderAndQ } = query;
|
|
13
|
+
const { folder, folderPath: _folderPath, _q, ...paramsExceptFolderAndQ } = query;
|
|
14
14
|
let params;
|
|
15
15
|
if (_q) {
|
|
16
16
|
params = {
|
|
@@ -24,8 +24,10 @@ const useAssets = ({ skipWhen = false, query = {} } = {})=>{
|
|
|
24
24
|
$and: [
|
|
25
25
|
...paramsExceptFolderAndQ?.filters?.$and ?? [],
|
|
26
26
|
{
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
folder: {
|
|
28
|
+
id: folder ?? {
|
|
29
|
+
$null: true
|
|
30
|
+
}
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssets.mjs","sources":["../../../admin/src/hooks/useAssets.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { useNotification, useFetchClient } from '@strapi/admin/strapi-admin';\nimport { useNotifyAT } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { useQuery } from 'react-query';\n\nimport { Query, GetFiles } from '../../../shared/contracts/files';\nimport { pluginId } from '../pluginId';\n\ninterface UseAssetsOptions {\n skipWhen?: boolean;\n query?: Query;\n}\n\nexport const useAssets = ({ skipWhen = false, query = {} }: UseAssetsOptions = {}) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { notifyStatus } = useNotifyAT();\n const { get } = useFetchClient();\n const { folderPath, _q, ...paramsExceptFolderAndQ } = query;\n\n let params: Query;\n\n if (_q) {\n params = {\n ...paramsExceptFolderAndQ,\n _q: encodeURIComponent(_q),\n };\n } else {\n params = {\n ...paramsExceptFolderAndQ,\n filters: {\n $and: [\n ...(paramsExceptFolderAndQ?.filters?.$and ?? []),\n {\n
|
|
1
|
+
{"version":3,"file":"useAssets.mjs","sources":["../../../admin/src/hooks/useAssets.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { useNotification, useFetchClient } from '@strapi/admin/strapi-admin';\nimport { useNotifyAT } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { useQuery } from 'react-query';\n\nimport { Query, GetFiles } from '../../../shared/contracts/files';\nimport { pluginId } from '../pluginId';\n\ninterface UseAssetsOptions {\n skipWhen?: boolean;\n query?: Query;\n}\n\nexport const useAssets = ({ skipWhen = false, query = {} }: UseAssetsOptions = {}) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { notifyStatus } = useNotifyAT();\n const { get } = useFetchClient();\n const { folder, folderPath: _folderPath, _q, ...paramsExceptFolderAndQ } = query;\n\n let params: Query;\n\n if (_q) {\n params = {\n ...paramsExceptFolderAndQ,\n _q: encodeURIComponent(_q),\n };\n } else {\n params = {\n ...paramsExceptFolderAndQ,\n filters: {\n $and: [\n ...(paramsExceptFolderAndQ?.filters?.$and ?? []),\n {\n folder: {\n id: folder ?? {\n $null: true,\n },\n },\n },\n ],\n },\n };\n }\n\n const { data, error, isLoading } = useQuery<\n GetFiles.Response['data'],\n GetFiles.Response['error']\n >(\n [pluginId, 'assets', params],\n async () => {\n const { data } = await get('/upload/files', { params });\n\n return data;\n },\n {\n enabled: !skipWhen,\n staleTime: 0,\n cacheTime: 0,\n select(data) {\n if (data?.results && Array.isArray(data.results)) {\n return {\n ...data,\n results: data.results\n /**\n * Filter out assets that don't have a name.\n * So we don't try to render them as assets\n * and get errors.\n */\n .filter((asset) => asset.name)\n .map((asset) => ({\n ...asset,\n /**\n * Mime and ext cannot be null in the front-end because\n * we expect them to be strings and use the `includes` method.\n */\n mime: asset.mime ?? '',\n ext: asset.ext ?? '',\n })),\n };\n }\n\n return data;\n },\n }\n );\n\n React.useEffect(() => {\n if (data) {\n notifyStatus(\n formatMessage({\n id: 'list.asset.at.finished',\n defaultMessage: 'The assets have finished loading.',\n })\n );\n }\n }, [data, formatMessage, notifyStatus]);\n\n React.useEffect(() => {\n if (error) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error' }),\n });\n }\n }, [error, formatMessage, toggleNotification]);\n\n return { data, error, isLoading };\n};\n"],"names":["useAssets","skipWhen","query","formatMessage","useIntl","toggleNotification","useNotification","notifyStatus","useNotifyAT","get","useFetchClient","folder","folderPath","_folderPath","_q","paramsExceptFolderAndQ","params","encodeURIComponent","filters","$and","id","$null","data","error","isLoading","useQuery","pluginId","enabled","staleTime","cacheTime","select","results","Array","isArray","filter","asset","name","map","mime","ext","React","useEffect","defaultMessage","type","message"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ export interface Asset extends Omit<FileDefinition, 'folder'> {
|
|
|
8
8
|
}
|
|
9
9
|
interface EditAssetContentProps {
|
|
10
10
|
asset?: Asset;
|
|
11
|
+
initialFolderId?: string | number | null;
|
|
11
12
|
canUpdate?: boolean;
|
|
12
13
|
canCopyLink?: boolean;
|
|
13
14
|
canDownload?: boolean;
|
|
@@ -16,7 +17,7 @@ interface EditAssetContentProps {
|
|
|
16
17
|
omitFields?: ('caption' | 'alternativeText')[];
|
|
17
18
|
omitActions?: 'replace'[];
|
|
18
19
|
}
|
|
19
|
-
export declare const EditAssetContent: ({ onClose, asset, canUpdate, canCopyLink, canDownload, trackedLocation, omitFields, omitActions, }: EditAssetContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare const EditAssetContent: ({ onClose, asset, initialFolderId, canUpdate, canCopyLink, canDownload, trackedLocation, omitFields, omitActions, }: EditAssetContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
21
|
interface EditAssetDialogProps {
|
|
21
22
|
asset: Asset;
|
|
22
23
|
canUpdate?: boolean;
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { AssetWithPopulatedCreatedBy } from '../../../../../../../shared/contracts/files';
|
|
3
|
+
interface DrawerToast {
|
|
4
|
+
type: 'success' | 'danger';
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
type DrawerNotify = (toast: DrawerToast) => void;
|
|
8
|
+
export declare const DrawerNotifyContext: React.Context<DrawerNotify | null>;
|
|
9
|
+
interface AssetOperations {
|
|
10
|
+
replaceAsset: (file: globalThis.File) => Promise<void>;
|
|
11
|
+
deleteAsset: () => Promise<void>;
|
|
12
|
+
isReplacing: boolean;
|
|
13
|
+
isDeleting: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare const AssetOperationsContext: React.Context<AssetOperations | null>;
|
|
3
16
|
export declare const useAssetDetailsParam: () => {
|
|
4
17
|
assetId: number | null;
|
|
5
18
|
isVisible: boolean;
|
|
@@ -10,7 +23,8 @@ export declare const useAssetDetailsParam: () => {
|
|
|
10
23
|
};
|
|
11
24
|
interface AssetDetailsProps {
|
|
12
25
|
asset: AssetWithPopulatedCreatedBy;
|
|
26
|
+
closeDetails: () => void;
|
|
13
27
|
}
|
|
14
|
-
export declare const AssetDetails: ({ asset }: AssetDetailsProps) => import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export declare const AssetDetails: ({ asset, closeDetails }: AssetDetailsProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
29
|
export declare const AssetDetailsDrawer: () => import("react/jsx-runtime").JSX.Element | null;
|
|
16
30
|
export {};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import type { File, AssetWithPopulatedCreatedBy } from '../../../../../../../shared/contracts/files';
|
|
2
3
|
interface AssetPreviewProps {
|
|
3
4
|
asset: File | AssetWithPopulatedCreatedBy;
|
|
5
|
+
actions?: React.ReactNode;
|
|
6
|
+
isLoading?: boolean;
|
|
4
7
|
}
|
|
5
|
-
export declare const AssetPreview: ({ asset }: AssetPreviewProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const AssetPreview: ({ asset, actions, isLoading }: AssetPreviewProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
9
|
export {};
|