@strapi/upload 5.51.2 → 5.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/future/App.js +3 -3
- package/dist/admin/future/App.js.map +1 -1
- package/dist/admin/future/App.mjs +4 -4
- package/dist/admin/future/App.mjs.map +1 -1
- package/dist/admin/future/components/BetaNotice.js +72 -0
- package/dist/admin/future/components/BetaNotice.js.map +1 -0
- package/dist/admin/future/components/BetaNotice.mjs +70 -0
- package/dist/admin/future/components/BetaNotice.mjs.map +1 -0
- package/dist/admin/future/components/Drawer.js +16 -3
- package/dist/admin/future/components/Drawer.js.map +1 -1
- package/dist/admin/future/components/Drawer.mjs +16 -3
- package/dist/admin/future/components/Drawer.mjs.map +1 -1
- package/dist/admin/future/hooks/useAIMetadataEnabled.js +39 -0
- package/dist/admin/future/hooks/useAIMetadataEnabled.js.map +1 -0
- package/dist/admin/future/hooks/useAIMetadataEnabled.mjs +37 -0
- package/dist/admin/future/hooks/useAIMetadataEnabled.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js +297 -139
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +301 -143
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.js +46 -0
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.mjs +44 -0
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +325 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +323 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +35 -14
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +35 -14
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +54 -53
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +54 -54
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +89 -24
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +91 -26
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +15 -3
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +16 -4
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +168 -58
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +171 -61
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +64 -132
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +64 -132
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js +123 -76
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs +126 -79
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BusyOverlay.js +36 -0
- package/dist/admin/future/pages/Assets/components/BusyOverlay.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/BusyOverlay.mjs +34 -0
- package/dist/admin/future/pages/Assets/components/BusyOverlay.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.js +131 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.mjs +129 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +27 -17
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +28 -18
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.js +28 -31
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.mjs +28 -31
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js +10 -15
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs +10 -15
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterBadges.js +13 -4
- package/dist/admin/future/pages/Assets/components/FilterBadges.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterBadges.mjs +13 -4
- package/dist/admin/future/pages/Assets/components/FilterBadges.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.js +241 -61
- package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +244 -64
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js +144 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs +142 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.js → FolderFormDialog.js} +50 -16
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.mjs → FolderFormDialog.mjs} +52 -18
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +111 -191
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +114 -194
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.js +47 -0
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.mjs +44 -0
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +203 -62
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +204 -63
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.js +75 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.mjs +73 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.mjs.map +1 -0
- package/dist/admin/future/services/api.js +24 -0
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +24 -0
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +11 -0
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +11 -0
- package/dist/admin/future/services/assets.mjs.map +1 -1
- package/dist/admin/future/services/folders.js +37 -2
- package/dist/admin/future/services/folders.js.map +1 -1
- package/dist/admin/future/services/folders.mjs +37 -3
- package/dist/admin/future/services/folders.mjs.map +1 -1
- package/dist/admin/future/utils/buildDragSetFromSelection.js +7 -5
- package/dist/admin/future/utils/buildDragSetFromSelection.js.map +1 -1
- package/dist/admin/future/utils/buildDragSetFromSelection.mjs +7 -5
- package/dist/admin/future/utils/buildDragSetFromSelection.mjs.map +1 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.js +12 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.js.map +1 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.mjs +12 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.mjs.map +1 -1
- package/dist/admin/future/utils/getRelationId.js +24 -0
- package/dist/admin/future/utils/getRelationId.js.map +1 -0
- package/dist/admin/future/utils/getRelationId.mjs +22 -0
- package/dist/admin/future/utils/getRelationId.mjs.map +1 -0
- package/dist/admin/future/utils/isEventFromWithin.js +14 -0
- package/dist/admin/future/utils/isEventFromWithin.js.map +1 -0
- package/dist/admin/future/utils/isEventFromWithin.mjs +12 -0
- package/dist/admin/future/utils/isEventFromWithin.mjs.map +1 -0
- package/dist/admin/future/utils/itemLocations.js +40 -0
- package/dist/admin/future/utils/itemLocations.js.map +1 -0
- package/dist/admin/future/utils/itemLocations.mjs +36 -0
- package/dist/admin/future/utils/itemLocations.mjs.map +1 -0
- package/dist/admin/future/utils/itemSource.js +36 -0
- package/dist/admin/future/utils/itemSource.js.map +1 -0
- package/dist/admin/future/utils/itemSource.mjs +32 -0
- package/dist/admin/future/utils/itemSource.mjs.map +1 -0
- package/dist/admin/index.js +11 -17
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +12 -18
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/future/App.d.ts +1 -1
- package/dist/admin/src/future/components/BetaNotice.d.ts +11 -0
- package/dist/admin/src/future/components/Drawer.d.ts +5 -1
- package/dist/admin/src/future/hooks/useAIMetadataEnabled.d.ts +26 -0
- package/dist/admin/src/future/pages/Assets/components/ActionsMenuContent.d.ts +33 -0
- package/dist/admin/src/future/pages/Assets/components/AssetActionsMenu.d.ts +24 -0
- package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +16 -0
- package/dist/admin/src/future/pages/Assets/components/BulkActionsBar.d.ts +8 -1
- package/dist/admin/src/future/pages/Assets/components/BulkMoveDialog.d.ts +17 -6
- package/dist/admin/src/future/pages/Assets/components/BusyOverlay.d.ts +9 -0
- package/dist/admin/src/future/pages/Assets/components/DeleteItemsDialog.d.ts +27 -0
- package/dist/admin/src/future/pages/Assets/components/Dnd/AssetsDndProvider.d.ts +8 -1
- package/dist/admin/src/future/pages/Assets/components/Dnd/buildDragSet.d.ts +18 -3
- package/dist/admin/src/future/pages/Assets/components/Dnd/useAssetDnd.d.ts +2 -1
- package/dist/admin/src/future/pages/Assets/components/FilterBadges.d.ts +3 -1
- package/dist/admin/src/future/pages/Assets/components/FilterMenu.d.ts +4 -0
- package/dist/admin/src/future/pages/Assets/components/FolderActionsMenu.d.ts +20 -0
- package/dist/admin/src/future/pages/Assets/components/FolderFormDialog.d.ts +16 -0
- package/dist/admin/src/future/pages/Assets/hooks/useBusyAssets.d.ts +38 -0
- package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +20 -6
- package/dist/admin/src/future/pages/Assets/hooks/useInfiniteScrollSentinel.d.ts +41 -0
- package/dist/admin/src/future/services/folders.d.ts +6 -1
- package/dist/admin/src/future/utils/buildDragSetFromSelection.d.ts +4 -3
- package/dist/admin/src/future/utils/formatMoveSuccessMessage.d.ts +7 -1
- package/dist/admin/src/future/utils/getRelationId.d.ts +11 -0
- package/dist/admin/src/future/utils/isEventFromWithin.d.ts +11 -0
- package/dist/admin/src/future/utils/itemLocations.d.ts +31 -0
- package/dist/admin/src/future/utils/itemSource.d.ts +22 -0
- package/dist/admin/translations/en.json.js +25 -4
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +25 -4
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/services/image-manipulation.js.map +1 -1
- package/dist/server/services/image-manipulation.mjs.map +1 -1
- package/dist/server/src/services/image-manipulation.d.ts +0 -5
- package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
- package/package.json +9 -9
- package/dist/admin/future/pages/Assets/components/CreateFolderDialog.js.map +0 -1
- package/dist/admin/future/pages/Assets/components/CreateFolderDialog.mjs.map +0 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js +0 -33
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js.map +0 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs +0 -31
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs.map +0 -1
- package/dist/admin/src/future/pages/Assets/components/CreateFolderDialog.d.ts +0 -8
- package/dist/admin/src/future/pages/Assets/components/FolderTree/filterFolderTree.d.ts +0 -16
|
@@ -107,6 +107,12 @@ const assetsApi = uploadApi.injectEndpoints({
|
|
|
107
107
|
{
|
|
108
108
|
type: 'Asset',
|
|
109
109
|
id: 'LIST'
|
|
110
|
+
},
|
|
111
|
+
// The Location select routes a folder move through this mutation, which
|
|
112
|
+
// changes both folders' counts — refresh the folder header count.
|
|
113
|
+
{
|
|
114
|
+
type: 'Folder',
|
|
115
|
+
id: 'LIST'
|
|
110
116
|
}
|
|
111
117
|
]
|
|
112
118
|
}),
|
|
@@ -161,6 +167,11 @@ const assetsApi = uploadApi.injectEndpoints({
|
|
|
161
167
|
{
|
|
162
168
|
type: 'Asset',
|
|
163
169
|
id: 'LIST'
|
|
170
|
+
},
|
|
171
|
+
// Refresh the folder header count — deleting an asset changes it.
|
|
172
|
+
{
|
|
173
|
+
type: 'Folder',
|
|
174
|
+
id: 'LIST'
|
|
164
175
|
}
|
|
165
176
|
]
|
|
166
177
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.mjs","sources":["../../../../admin/src/future/services/assets.ts"],"sourcesContent":["import { encodeSearchQuery } from '../utils/searchQueryParam';\n\nimport { uploadApi } from './api';\n\nimport type {\n GetFiles,\n File,\n Pagination,\n UploadFileInfo,\n AssetWithPopulatedCreatedBy,\n} from '../../../../shared/contracts/files';\n\ninterface GetAssetsParams {\n page?: number;\n pageSize?: number;\n folder?: number | null;\n sort?: string;\n search?: string;\n /** Extra `filters[$and]` entries (list filters), AND-ed with the folder/search scope. */\n filters?: Record<string, unknown>[];\n}\n\ninterface GetAssetsResponse {\n results: File[];\n pagination: Pagination;\n}\n\ninterface UpdateAssetArgs {\n id: number;\n fileInfo: Partial<UploadFileInfo>;\n}\n\ninterface ReplaceAssetArgs {\n id: number;\n // `File` is shadowed in this module by the asset-file contract type; the\n // global browser File is what we need for FormData.\n file: globalThis.File;\n fileInfo?: Partial<UploadFileInfo>;\n}\n\nconst assetsApi = uploadApi.injectEndpoints({\n endpoints: (builder) => ({\n getAssets: builder.query<GetAssetsResponse, GetAssetsParams | void>({\n query: (params = {}) => {\n // `search` is destructured out so it never reaches the server as-is —\n // it is re-added below as the `_q` the API actually understands.\n const { folder, search, filters = [], ...rest } = params as GetAssetsParams;\n\n const queryParams: Record<string, unknown> = { ...rest };\n\n // List filters apply in BOTH modes: search composes with them (a\n // filtered search), only the folder scope is dropped while searching.\n if (search) {\n // Search is global: folder scoping is intentionally dropped so results span the whole library.\n queryParams['_q'] = encodeSearchQuery(search);\n\n if (filters.length > 0) {\n queryParams['filters'] = { $and: [...filters] };\n }\n } else {\n const folderScope =\n folder != null ? { folder: { id: folder } } : { folder: { id: { $null: true } } };\n\n queryParams['filters'] = {\n $and: [folderScope, ...filters],\n };\n }\n\n return {\n url: '/upload/files',\n method: 'GET',\n config: { params: queryParams },\n };\n },\n transformResponse: (response: GetFiles.Response['data']) => response,\n providesTags: (result) =>\n result\n ? [\n ...result.results.map(({ id }) => ({ type: 'Asset' as const, id })),\n { type: 'Asset', id: 'LIST' },\n ]\n : [{ type: 'Asset', id: 'LIST' }],\n }),\n getAsset: builder.query<AssetWithPopulatedCreatedBy, number>({\n query: (id) => ({\n url: `/upload/files/${id}`,\n method: 'GET',\n }),\n providesTags: (_result, _error, id) => [{ type: 'Asset' as const, id }],\n }),\n /**\n * Update the editable metadata of an existing asset.\n * Hits the legacy `POST /upload?id=<id>` endpoint which dispatches to\n * `admin-upload.updateFileInfo`.\n */\n updateAsset: builder.mutation<AssetWithPopulatedCreatedBy, UpdateAssetArgs>({\n query: ({ id, fileInfo }) => {\n const formData = new FormData();\n formData.append('fileInfo', JSON.stringify(fileInfo));\n\n return {\n url: '/upload',\n method: 'POST',\n data: formData,\n config: { params: { id } },\n };\n },\n invalidatesTags: (_result, _error, { id }) => [\n { type: 'Asset' as const, id },\n { type: 'Asset' as const, id: 'LIST' },\n ],\n }),\n /**\n * Replace the binary content of an existing asset.\n * Hits `POST /upload?id=<id>` with a multipart body — the controller\n * dispatches to `admin-upload.replaceFile` when a `files` part is present.\n * Uses the standard axios baseQuery (no streaming) since we only ever\n * replace one file at a time and don't need per-byte progress here.\n */\n replaceAsset: builder.mutation<AssetWithPopulatedCreatedBy, ReplaceAssetArgs>({\n query: ({ id, file, fileInfo }) => {\n const formData = new FormData();\n formData.append('files', file);\n if (fileInfo) {\n formData.append('fileInfo', JSON.stringify(fileInfo));\n }\n return {\n url: '/upload',\n method: 'POST',\n data: formData,\n config: { params: { id } },\n };\n },\n invalidatesTags: (_result, _error, { id }) => [\n { type: 'Asset' as const, id },\n { type: 'Asset' as const, id: 'LIST' },\n ],\n }),\n /**\n * Permanently delete an asset by id. Hits the same endpoint as the legacy\n * `useRemoveAsset` hook so server behaviour is unchanged.\n */\n deleteAsset: builder.mutation<unknown, number>({\n query: (id) => ({\n url: `/upload/files/${id}`,\n method: 'DELETE',\n }),\n invalidatesTags: (_result, _error, id) => [\n { type: 'Asset' as const, id },\n { type: 'Asset' as const, id: 'LIST' },\n ],\n }),\n /**\n * Permanently delete several assets and/or folders in one request. Same\n * endpoint as the legacy bulk remove (`POST /upload/actions/bulk-delete`,\n * handled by `admin-folder-file.deleteMany`) so server behaviour is\n * unchanged — folder deletion cascades to everything inside.\n */\n bulkDeleteItems: builder.mutation<unknown, { fileIds: number[]; folderIds: number[] }>({\n query: ({ fileIds, folderIds }) => ({\n url: '/upload/actions/bulk-delete',\n method: 'POST',\n data: { fileIds, folderIds },\n }),\n invalidatesTags: [\n { type: 'Asset' as const, id: 'LIST' },\n { type: 'Folder' as const, id: 'LIST' },\n // The sidebar FolderTree reads /upload/folder-structure, which carries\n // its own tag — without it, deleted folders linger in the tree.\n { type: 'Folder' as const, id: 'STRUCTURE' },\n ],\n }),\n }),\n});\n\nexport const {\n useGetAssetsQuery,\n useGetAssetQuery,\n useUpdateAssetMutation,\n useReplaceAssetMutation,\n useDeleteAssetMutation,\n useBulkDeleteItemsMutation,\n} = assetsApi;\n\n/**\n * `generateAiMetadata` is defined in `./api` (the upload flows dispatch it directly\n * after each file completes, and this module imports from there) — re-exported here\n * so asset components keep a single import site for asset-related hooks.\n */\nexport { useGenerateAiMetadataMutation } from './api';\n"],"names":["assetsApi","uploadApi","injectEndpoints","endpoints","builder","getAssets","query","params","folder","search","filters","rest","queryParams","encodeSearchQuery","length","$and","folderScope","id","$null","url","method","config","transformResponse","response","providesTags","result","results","map","type","getAsset","_result","_error","updateAsset","mutation","fileInfo","formData","FormData","append","JSON","stringify","data","invalidatesTags","replaceAsset","file","deleteAsset","bulkDeleteItems","fileIds","folderIds","useGetAssetsQuery","useGetAssetQuery","useUpdateAssetMutation","useReplaceAssetMutation","useDeleteAssetMutation","useBulkDeleteItemsMutation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"assets.mjs","sources":["../../../../admin/src/future/services/assets.ts"],"sourcesContent":["import { encodeSearchQuery } from '../utils/searchQueryParam';\n\nimport { uploadApi } from './api';\n\nimport type {\n GetFiles,\n File,\n Pagination,\n UploadFileInfo,\n AssetWithPopulatedCreatedBy,\n} from '../../../../shared/contracts/files';\n\ninterface GetAssetsParams {\n page?: number;\n pageSize?: number;\n folder?: number | null;\n sort?: string;\n search?: string;\n /** Extra `filters[$and]` entries (list filters), AND-ed with the folder/search scope. */\n filters?: Record<string, unknown>[];\n}\n\ninterface GetAssetsResponse {\n results: File[];\n pagination: Pagination;\n}\n\ninterface UpdateAssetArgs {\n id: number;\n fileInfo: Partial<UploadFileInfo>;\n}\n\ninterface ReplaceAssetArgs {\n id: number;\n // `File` is shadowed in this module by the asset-file contract type; the\n // global browser File is what we need for FormData.\n file: globalThis.File;\n fileInfo?: Partial<UploadFileInfo>;\n}\n\nconst assetsApi = uploadApi.injectEndpoints({\n endpoints: (builder) => ({\n getAssets: builder.query<GetAssetsResponse, GetAssetsParams | void>({\n query: (params = {}) => {\n // `search` is destructured out so it never reaches the server as-is —\n // it is re-added below as the `_q` the API actually understands.\n const { folder, search, filters = [], ...rest } = params as GetAssetsParams;\n\n const queryParams: Record<string, unknown> = { ...rest };\n\n // List filters apply in BOTH modes: search composes with them (a\n // filtered search), only the folder scope is dropped while searching.\n if (search) {\n // Search is global: folder scoping is intentionally dropped so results span the whole library.\n queryParams['_q'] = encodeSearchQuery(search);\n\n if (filters.length > 0) {\n queryParams['filters'] = { $and: [...filters] };\n }\n } else {\n const folderScope =\n folder != null ? { folder: { id: folder } } : { folder: { id: { $null: true } } };\n\n queryParams['filters'] = {\n $and: [folderScope, ...filters],\n };\n }\n\n return {\n url: '/upload/files',\n method: 'GET',\n config: { params: queryParams },\n };\n },\n transformResponse: (response: GetFiles.Response['data']) => response,\n providesTags: (result) =>\n result\n ? [\n ...result.results.map(({ id }) => ({ type: 'Asset' as const, id })),\n { type: 'Asset', id: 'LIST' },\n ]\n : [{ type: 'Asset', id: 'LIST' }],\n }),\n getAsset: builder.query<AssetWithPopulatedCreatedBy, number>({\n query: (id) => ({\n url: `/upload/files/${id}`,\n method: 'GET',\n }),\n providesTags: (_result, _error, id) => [{ type: 'Asset' as const, id }],\n }),\n /**\n * Update the editable metadata of an existing asset.\n * Hits the legacy `POST /upload?id=<id>` endpoint which dispatches to\n * `admin-upload.updateFileInfo`.\n */\n updateAsset: builder.mutation<AssetWithPopulatedCreatedBy, UpdateAssetArgs>({\n query: ({ id, fileInfo }) => {\n const formData = new FormData();\n formData.append('fileInfo', JSON.stringify(fileInfo));\n\n return {\n url: '/upload',\n method: 'POST',\n data: formData,\n config: { params: { id } },\n };\n },\n invalidatesTags: (_result, _error, { id }) => [\n { type: 'Asset' as const, id },\n { type: 'Asset' as const, id: 'LIST' },\n // The Location select routes a folder move through this mutation, which\n // changes both folders' counts — refresh the folder header count.\n { type: 'Folder' as const, id: 'LIST' },\n ],\n }),\n /**\n * Replace the binary content of an existing asset.\n * Hits `POST /upload?id=<id>` with a multipart body — the controller\n * dispatches to `admin-upload.replaceFile` when a `files` part is present.\n * Uses the standard axios baseQuery (no streaming) since we only ever\n * replace one file at a time and don't need per-byte progress here.\n */\n replaceAsset: builder.mutation<AssetWithPopulatedCreatedBy, ReplaceAssetArgs>({\n query: ({ id, file, fileInfo }) => {\n const formData = new FormData();\n formData.append('files', file);\n if (fileInfo) {\n formData.append('fileInfo', JSON.stringify(fileInfo));\n }\n return {\n url: '/upload',\n method: 'POST',\n data: formData,\n config: { params: { id } },\n };\n },\n invalidatesTags: (_result, _error, { id }) => [\n { type: 'Asset' as const, id },\n { type: 'Asset' as const, id: 'LIST' },\n ],\n }),\n /**\n * Permanently delete an asset by id. Hits the same endpoint as the legacy\n * `useRemoveAsset` hook so server behaviour is unchanged.\n */\n deleteAsset: builder.mutation<unknown, number>({\n query: (id) => ({\n url: `/upload/files/${id}`,\n method: 'DELETE',\n }),\n invalidatesTags: (_result, _error, id) => [\n { type: 'Asset' as const, id },\n { type: 'Asset' as const, id: 'LIST' },\n // Refresh the folder header count — deleting an asset changes it.\n { type: 'Folder' as const, id: 'LIST' },\n ],\n }),\n /**\n * Permanently delete several assets and/or folders in one request. Same\n * endpoint as the legacy bulk remove (`POST /upload/actions/bulk-delete`,\n * handled by `admin-folder-file.deleteMany`) so server behaviour is\n * unchanged — folder deletion cascades to everything inside.\n */\n bulkDeleteItems: builder.mutation<unknown, { fileIds: number[]; folderIds: number[] }>({\n query: ({ fileIds, folderIds }) => ({\n url: '/upload/actions/bulk-delete',\n method: 'POST',\n data: { fileIds, folderIds },\n }),\n invalidatesTags: [\n { type: 'Asset' as const, id: 'LIST' },\n { type: 'Folder' as const, id: 'LIST' },\n // The sidebar FolderTree reads /upload/folder-structure, which carries\n // its own tag — without it, deleted folders linger in the tree.\n { type: 'Folder' as const, id: 'STRUCTURE' },\n ],\n }),\n }),\n});\n\nexport const {\n useGetAssetsQuery,\n useGetAssetQuery,\n useUpdateAssetMutation,\n useReplaceAssetMutation,\n useDeleteAssetMutation,\n useBulkDeleteItemsMutation,\n} = assetsApi;\n\n/**\n * `generateAiMetadata` is defined in `./api` (the upload flows dispatch it directly\n * after each file completes, and this module imports from there) — re-exported here\n * so asset components keep a single import site for asset-related hooks.\n */\nexport { useGenerateAiMetadataMutation } from './api';\n"],"names":["assetsApi","uploadApi","injectEndpoints","endpoints","builder","getAssets","query","params","folder","search","filters","rest","queryParams","encodeSearchQuery","length","$and","folderScope","id","$null","url","method","config","transformResponse","response","providesTags","result","results","map","type","getAsset","_result","_error","updateAsset","mutation","fileInfo","formData","FormData","append","JSON","stringify","data","invalidatesTags","replaceAsset","file","deleteAsset","bulkDeleteItems","fileIds","folderIds","useGetAssetsQuery","useGetAssetQuery","useUpdateAssetMutation","useReplaceAssetMutation","useDeleteAssetMutation","useBulkDeleteItemsMutation"],"mappings":"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"}
|
|
@@ -12,7 +12,10 @@ const foldersApi = api.uploadApi.injectEndpoints({
|
|
|
12
12
|
const { parentId, sort, search, filters = [] } = params;
|
|
13
13
|
const queryParams = {
|
|
14
14
|
// Default matches sidebar FolderTree order (server getStructure uses sortBy('name')).
|
|
15
|
-
sort: sort ?? 'name:ASC'
|
|
15
|
+
sort: sort ?? 'name:ASC',
|
|
16
|
+
populate: {
|
|
17
|
+
parent: true
|
|
18
|
+
}
|
|
16
19
|
};
|
|
17
20
|
// List filters (dates) apply in BOTH modes — search composes with them,
|
|
18
21
|
// only the parent scope is dropped while searching.
|
|
@@ -96,6 +99,28 @@ const foldersApi = api.uploadApi.injectEndpoints({
|
|
|
96
99
|
}
|
|
97
100
|
]
|
|
98
101
|
}),
|
|
102
|
+
updateFolder: builder.mutation({
|
|
103
|
+
query: ({ id, ...body })=>({
|
|
104
|
+
url: `/upload/folders/${id}`,
|
|
105
|
+
method: 'PUT',
|
|
106
|
+
data: body
|
|
107
|
+
}),
|
|
108
|
+
transformResponse: (response)=>response.data,
|
|
109
|
+
invalidatesTags: (_result, _error, { id })=>[
|
|
110
|
+
{
|
|
111
|
+
type: 'Folder',
|
|
112
|
+
id
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: 'Folder',
|
|
116
|
+
id: 'LIST'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
type: 'Folder',
|
|
120
|
+
id: 'STRUCTURE'
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
}),
|
|
99
124
|
/**
|
|
100
125
|
* Hierarchical folder tree used by the FolderTree sidebar. Returned as a
|
|
101
126
|
* single nested array — the server walks the folders table once and
|
|
@@ -172,10 +197,19 @@ const foldersApi = api.uploadApi.injectEndpoints({
|
|
|
172
197
|
}
|
|
173
198
|
}),
|
|
174
199
|
transformResponse: (response)=>response.data,
|
|
200
|
+
// Also carries the LIST tag so a mutation that changes a folder's file
|
|
201
|
+
// count (upload / delete into it) can refresh the header count by
|
|
202
|
+
// invalidating `{ Folder, LIST }`, without needing the folder id at the
|
|
203
|
+
// mutation site (it's buried in the upload FormData / not passed to the
|
|
204
|
+
// delete).
|
|
175
205
|
providesTags: (_result, _error, { id })=>[
|
|
176
206
|
{
|
|
177
207
|
type: 'Folder',
|
|
178
208
|
id
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
type: 'Folder',
|
|
212
|
+
id: 'LIST'
|
|
179
213
|
}
|
|
180
214
|
]
|
|
181
215
|
}),
|
|
@@ -207,7 +241,7 @@ const foldersApi = api.uploadApi.injectEndpoints({
|
|
|
207
241
|
})
|
|
208
242
|
})
|
|
209
243
|
});
|
|
210
|
-
const { useCreateFolderMutation, useGetFoldersQuery, useGetFolderQuery, useGetAllFoldersQuery, useGetFolderStructureQuery, useBulkMoveMutation } = foldersApi;
|
|
244
|
+
const { useCreateFolderMutation, useUpdateFolderMutation, useGetFoldersQuery, useGetFolderQuery, useGetAllFoldersQuery, useGetFolderStructureQuery, useBulkMoveMutation } = foldersApi;
|
|
211
245
|
|
|
212
246
|
exports.useBulkMoveMutation = useBulkMoveMutation;
|
|
213
247
|
exports.useCreateFolderMutation = useCreateFolderMutation;
|
|
@@ -215,4 +249,5 @@ exports.useGetAllFoldersQuery = useGetAllFoldersQuery;
|
|
|
215
249
|
exports.useGetFolderQuery = useGetFolderQuery;
|
|
216
250
|
exports.useGetFolderStructureQuery = useGetFolderStructureQuery;
|
|
217
251
|
exports.useGetFoldersQuery = useGetFoldersQuery;
|
|
252
|
+
exports.useUpdateFolderMutation = useUpdateFolderMutation;
|
|
218
253
|
//# sourceMappingURL=folders.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"folders.js","sources":["../../../../admin/src/future/services/folders.ts"],"sourcesContent":["import { encodeSearchQuery } from '../utils/searchQueryParam';\n\nimport { uploadApi } from './api';\n\nimport type {\n Folder,\n FolderNode,\n CreateFolders,\n GetFolder,\n GetFolders,\n GetFolderStructure,\n BulkMoveFolders,\n} from '../../../../shared/contracts/folders';\n\nexport type FolderWithCounts = Omit<Folder, 'children' | 'files'> & {\n children?: { count: number };\n files?: { count: number };\n};\n\ninterface GetFoldersParams {\n parentId?: number | null;\n /** Comma-separated rules, e.g. `updatedAt:DESC,name:ASC`. Defaults to alphabetical. */\n sort?: string;\n search?: string;\n /** Extra `filters[$and]` entries (list filters), AND-ed with the parent/search scope. */\n filters?: Record<string, unknown>[];\n}\n\ninterface BulkMoveParams {\n fileIds?: number[];\n folderIds?: number[];\n /** `null` moves the items to the root of the Media Library. */\n destinationFolderId: number | null;\n}\n\ntype DataEnvelope<T> = {\n data: T;\n};\n\nconst isDataEnvelope = <T>(response: T | DataEnvelope<T>): response is DataEnvelope<T> =>\n typeof response === 'object' && response !== null && 'data' in response;\n\nconst unwrapData = <T>(response: T | DataEnvelope<T>): T =>\n isDataEnvelope(response) ? response.data : response;\n\nconst foldersApi = uploadApi.injectEndpoints({\n endpoints: (builder) => ({\n getFolders: builder.query<Folder[], GetFoldersParams | void>({\n query: (params = {}) => {\n const { parentId, sort, search, filters = [] } = params as GetFoldersParams;\n\n const queryParams: Record<string, unknown> = {\n // Default matches sidebar FolderTree order (server getStructure uses sortBy('name')).\n sort: sort ?? 'name:ASC',\n };\n\n // List filters (dates) apply in BOTH modes — search composes with them,\n // only the parent scope is dropped while searching.\n if (search) {\n // Search is global: the parent filter is dropped so matching folders\n // anywhere in the library surface. The endpoint is unpaginated — it\n // returns every match — so callers can treat the array length as the\n // true total. Bounding it is a separate decision.\n queryParams['_q'] = encodeSearchQuery(search);\n\n if (filters.length > 0) {\n queryParams['filters'] = { $and: [...filters] };\n }\n } else {\n const parentScope =\n parentId != null ? { parent: { id: parentId } } : { parent: { id: { $null: true } } };\n\n queryParams['filters'] = {\n $and: [parentScope, ...filters],\n };\n }\n\n return {\n url: '/upload/folders',\n method: 'GET',\n config: { params: queryParams },\n };\n },\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder', id: 'LIST' },\n ];\n }\n return [{ type: 'Folder', id: 'LIST' }];\n },\n }),\n createFolder: builder.mutation<CreateFolders.Response['data'], CreateFolders.Request['body']>({\n query: (body) => ({\n url: '/upload/folders',\n method: 'POST',\n data: body,\n }),\n transformResponse: (response: CreateFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n /**\n * Hierarchical folder tree used by the FolderTree sidebar. Returned as a\n * single nested array — the server walks the folders table once and\n * assembles parent/child relationships.\n *\n * TODO: filter results like `admin-folder.find` for folder-scoped roles\n * (v1 returns all folders; relies on global `plugin::upload.read`).\n */\n getFolderStructure: builder.query<FolderNode[], void>({\n query: () => ({\n url: '/upload/folder-structure',\n method: 'GET',\n }),\n // TODO: align GetFolderStructure contract with the real /upload/folder-structure\n // envelope and drop this defensive unwrap (data[] vs { data: [] }).\n transformResponse: (response: GetFolderStructure.Response['data']) =>\n ((response as unknown as { data: FolderNode[] })?.data ??\n (response as unknown as FolderNode[]) ??\n []) as FolderNode[],\n providesTags: [{ type: 'Folder', id: 'STRUCTURE' }],\n }),\n /**\n * Flat list of every folder, used to populate the \"Location\" select in the\n * asset details drawer. No parent filter — we want the entire tree in one\n * query so the select can render any destination folder.\n */\n getAllFolders: builder.query<Folder[], void>({\n query: () => ({\n url: '/upload/folders',\n method: 'GET',\n }),\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response ?? []),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder' as const, id: 'LIST' },\n ];\n }\n return [{ type: 'Folder' as const, id: 'LIST' }];\n },\n }),\n getFolder: builder.query<FolderWithCounts, { id: number }>({\n query: ({ id }) => ({\n url: `/upload/folders/${id}`,\n method: 'GET',\n config: {\n params: {\n populate: {\n parent: {\n populate: {\n parent: '*',\n },\n },\n children: { count: true },\n files: { count: true },\n },\n },\n },\n }),\n transformResponse: (response: GetFolder.Response) =>\n response.data as unknown as FolderWithCounts,\n providesTags: (_result, _error, { id }) => [{ type: 'Folder', id }],\n }),\n bulkMove: builder.mutation<BulkMoveFolders.Response['data'], BulkMoveParams>({\n query: ({ fileIds = [], folderIds = [], destinationFolderId }) => ({\n url: '/upload/actions/bulk-move',\n method: 'POST',\n data: { fileIds, folderIds, destinationFolderId },\n }),\n transformResponse: (response: BulkMoveFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Asset', id: 'LIST' },\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n }),\n});\n\nexport const {\n useCreateFolderMutation,\n useGetFoldersQuery,\n useGetFolderQuery,\n useGetAllFoldersQuery,\n useGetFolderStructureQuery,\n useBulkMoveMutation,\n} = foldersApi;\n"],"names":["isDataEnvelope","response","unwrapData","data","foldersApi","uploadApi","injectEndpoints","endpoints","builder","getFolders","query","params","parentId","sort","search","filters","queryParams","encodeSearchQuery","length","$and","parentScope","parent","id","$null","url","method","config","transformResponse","providesTags","results","map","type","createFolder","mutation","body","invalidatesTags","getFolderStructure","getAllFolders","getFolder","populate","children","count","files","_result","_error","bulkMove","fileIds","folderIds","destinationFolderId","useCreateFolderMutation","useGetFoldersQuery","useGetFolderQuery","useGetAllFoldersQuery","useGetFolderStructureQuery","useBulkMoveMutation"],"mappings":";;;;;AAuCA,MAAMA,cAAAA,GAAiB,CAAIC,QAAAA,GACzB,OAAOA,aAAa,QAAA,IAAYA,QAAAA,KAAa,QAAQ,MAAA,IAAUA,QAAAA;AAEjE,MAAMC,aAAa,CAAID,QAAAA,GACrBD,eAAeC,QAAAA,CAAAA,GAAYA,QAAAA,CAASE,IAAI,GAAGF,QAAAA;AAE7C,MAAMG,UAAAA,GAAaC,aAAAA,CAAUC,eAAe,CAAC;IAC3CC,SAAAA,EAAW,CAACC,WAAa;YACvBC,UAAAA,EAAYD,OAAAA,CAAQE,KAAK,CAAoC;gBAC3DA,KAAAA,EAAO,CAACC,MAAAA,GAAS,EAAE,GAAA;oBACjB,MAAM,EAAEC,QAAQ,EAAEC,IAAI,EAAEC,MAAM,EAAEC,OAAAA,GAAU,EAAE,EAAE,GAAGJ,MAAAA;AAEjD,oBAAA,MAAMK,WAAAA,GAAuC;;AAE3CH,wBAAAA,IAAAA,EAAMA,IAAAA,IAAQ;AAChB,qBAAA;;;AAIA,oBAAA,IAAIC,MAAAA,EAAQ;;;;;wBAKVE,WAAW,CAAC,IAAA,CAAK,GAAGC,kCAAAA,CAAkBH,MAAAA,CAAAA;wBAEtC,IAAIC,OAAAA,CAAQG,MAAM,GAAG,CAAA,EAAG;4BACtBF,WAAW,CAAC,UAAU,GAAG;gCAAEG,IAAAA,EAAM;AAAIJ,oCAAAA,GAAAA;AAAQ;AAAC,6BAAA;AAChD,wBAAA;oBACF,CAAA,MAAO;wBACL,MAAMK,WAAAA,GACJR,YAAY,IAAA,GAAO;4BAAES,MAAAA,EAAQ;gCAAEC,EAAAA,EAAIV;AAAS;yBAAE,GAAI;4BAAES,MAAAA,EAAQ;gCAAEC,EAAAA,EAAI;oCAAEC,KAAAA,EAAO;AAAK;AAAE;AAAE,yBAAA;wBAEtFP,WAAW,CAAC,UAAU,GAAG;4BACvBG,IAAAA,EAAM;AAACC,gCAAAA,WAAAA;AAAgBL,gCAAAA,GAAAA;AAAQ;AACjC,yBAAA;AACF,oBAAA;oBAEA,OAAO;wBACLS,GAAAA,EAAK,iBAAA;wBACLC,MAAAA,EAAQ,KAAA;wBACRC,MAAAA,EAAQ;4BAAEf,MAAAA,EAAQK;AAAY;AAChC,qBAAA;AACF,gBAAA,CAAA;gBACAW,iBAAAA,EAAmB,CAAC1B,WAClBC,UAAAA,CAAwCD,QAAAA,CAAAA;AAC1C2B,gBAAAA,YAAAA,EAAc,CAACC,OAAAA,GAAAA;AACb,oBAAA,IAAIA,OAAAA,EAAS;wBACX,OAAO;AACFA,4BAAAA,GAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,EAAER,EAAE,EAAE,IAAM;oCAAES,IAAAA,EAAM,QAAA;AAAmBT,oCAAAA;iCAAG,CAAA,CAAA;AAC1D,4BAAA;gCAAES,IAAAA,EAAM,QAAA;gCAAUT,EAAAA,EAAI;AAAO;AAC9B,yBAAA;AACH,oBAAA;oBACA,OAAO;AAAC,wBAAA;4BAAES,IAAAA,EAAM,QAAA;4BAAUT,EAAAA,EAAI;AAAO;AAAE,qBAAA;AACzC,gBAAA;AACF,aAAA,CAAA;YACAU,YAAAA,EAAcxB,OAAAA,CAAQyB,QAAQ,CAAgE;gBAC5FvB,KAAAA,EAAO,CAACwB,QAAU;wBAChBV,GAAAA,EAAK,iBAAA;wBACLC,MAAAA,EAAQ,MAAA;wBACRtB,IAAAA,EAAM+B;qBACR,CAAA;gBACAP,iBAAAA,EAAmB,CAAC1B,QAAAA,GAAqCA,QAAAA,CAASE,IAAI;gBACtEgC,eAAAA,EAAiB;AACf,oBAAA;wBAAEJ,IAAAA,EAAM,QAAA;wBAAUT,EAAAA,EAAI;AAAO,qBAAA;AAC7B,oBAAA;wBAAES,IAAAA,EAAM,QAAA;wBAAUT,EAAAA,EAAI;AAAY;AACnC;AACH,aAAA,CAAA;AACA;;;;;;;QAQAc,kBAAAA,EAAoB5B,OAAAA,CAAQE,KAAK,CAAqB;AACpDA,gBAAAA,KAAAA,EAAO,KAAO;wBACZc,GAAAA,EAAK,0BAAA;wBACLC,MAAAA,EAAQ;qBACV,CAAA;;;AAGAE,gBAAAA,iBAAAA,EAAmB,CAAC1B,QAAAA,GAChBA,QAAAA,EAAgDE,IAAAA,IAC/CF,YACD,EAAE;gBACN2B,YAAAA,EAAc;AAAC,oBAAA;wBAAEG,IAAAA,EAAM,QAAA;wBAAUT,EAAAA,EAAI;AAAY;AAAE;AACrD,aAAA,CAAA;AACA;;;;QAKAe,aAAAA,EAAe7B,OAAAA,CAAQE,KAAK,CAAiB;AAC3CA,gBAAAA,KAAAA,EAAO,KAAO;wBACZc,GAAAA,EAAK,iBAAA;wBACLC,MAAAA,EAAQ;qBACV,CAAA;AACAE,gBAAAA,iBAAAA,EAAmB,CAAC1B,QAAAA,GAClBC,UAAAA,CAAwCD,QAAAA,IAAY,EAAE,CAAA;AACxD2B,gBAAAA,YAAAA,EAAc,CAACC,OAAAA,GAAAA;AACb,oBAAA,IAAIA,OAAAA,EAAS;wBACX,OAAO;AACFA,4BAAAA,GAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,EAAER,EAAE,EAAE,IAAM;oCAAES,IAAAA,EAAM,QAAA;AAAmBT,oCAAAA;iCAAG,CAAA,CAAA;AAC1D,4BAAA;gCAAES,IAAAA,EAAM,QAAA;gCAAmBT,EAAAA,EAAI;AAAO;AACvC,yBAAA;AACH,oBAAA;oBACA,OAAO;AAAC,wBAAA;4BAAES,IAAAA,EAAM,QAAA;4BAAmBT,EAAAA,EAAI;AAAO;AAAE,qBAAA;AAClD,gBAAA;AACF,aAAA,CAAA;YACAgB,SAAAA,EAAW9B,OAAAA,CAAQE,KAAK,CAAmC;AACzDA,gBAAAA,KAAAA,EAAO,CAAC,EAAEY,EAAE,EAAE,IAAM;wBAClBE,GAAAA,EAAK,CAAC,gBAAgB,EAAEF,EAAAA,CAAAA,CAAI;wBAC5BG,MAAAA,EAAQ,KAAA;wBACRC,MAAAA,EAAQ;4BACNf,MAAAA,EAAQ;gCACN4B,QAAAA,EAAU;oCACRlB,MAAAA,EAAQ;wCACNkB,QAAAA,EAAU;4CACRlB,MAAAA,EAAQ;AACV;AACF,qCAAA;oCACAmB,QAAAA,EAAU;wCAAEC,KAAAA,EAAO;AAAK,qCAAA;oCACxBC,KAAAA,EAAO;wCAAED,KAAAA,EAAO;AAAK;AACvB;AACF;AACF;qBACF,CAAA;gBACAd,iBAAAA,EAAmB,CAAC1B,QAAAA,GAClBA,QAAAA,CAASE,IAAI;AACfyB,gBAAAA,YAAAA,EAAc,CAACe,OAAAA,EAASC,MAAAA,EAAQ,EAAEtB,EAAE,EAAE,GAAK;AAAC,wBAAA;4BAAES,IAAAA,EAAM,QAAA;AAAUT,4BAAAA;AAAG;AAAE;AACrE,aAAA,CAAA;YACAuB,QAAAA,EAAUrC,OAAAA,CAAQyB,QAAQ,CAAmD;gBAC3EvB,KAAAA,EAAO,CAAC,EAAEoC,OAAAA,GAAU,EAAE,EAAEC,SAAAA,GAAY,EAAE,EAAEC,mBAAmB,EAAE,IAAM;wBACjExB,GAAAA,EAAK,2BAAA;wBACLC,MAAAA,EAAQ,MAAA;wBACRtB,IAAAA,EAAM;AAAE2C,4BAAAA,OAAAA;AAASC,4BAAAA,SAAAA;AAAWC,4BAAAA;AAAoB;qBAClD,CAAA;gBACArB,iBAAAA,EAAmB,CAAC1B,QAAAA,GAAuCA,QAAAA,CAASE,IAAI;gBACxEgC,eAAAA,EAAiB;AACf,oBAAA;wBAAEJ,IAAAA,EAAM,OAAA;wBAAST,EAAAA,EAAI;AAAO,qBAAA;AAC5B,oBAAA;wBAAES,IAAAA,EAAM,QAAA;wBAAUT,EAAAA,EAAI;AAAO,qBAAA;AAC7B,oBAAA;wBAAES,IAAAA,EAAM,QAAA;wBAAUT,EAAAA,EAAI;AAAY;AACnC;AACH,aAAA;SACF;AACF,CAAA,CAAA;AAEO,MAAM,EACX2B,uBAAuB,EACvBC,kBAAkB,EAClBC,iBAAiB,EACjBC,qBAAqB,EACrBC,0BAA0B,EAC1BC,mBAAmB,EACpB,GAAGlD;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"folders.js","sources":["../../../../admin/src/future/services/folders.ts"],"sourcesContent":["import { encodeSearchQuery } from '../utils/searchQueryParam';\n\nimport { uploadApi } from './api';\n\nimport type {\n Folder,\n FolderNode,\n CreateFolders,\n GetFolder,\n GetFolders,\n GetFolderStructure,\n BulkMoveFolders,\n UpdateFolder,\n} from '../../../../shared/contracts/folders';\n\nexport type FolderWithCounts = Omit<Folder, 'children' | 'files'> & {\n children?: { count: number };\n files?: { count: number };\n};\n\ninterface GetFoldersParams {\n parentId?: number | null;\n /** Comma-separated rules, e.g. `updatedAt:DESC,name:ASC`. Defaults to alphabetical. */\n sort?: string;\n search?: string;\n /** Extra `filters[$and]` entries (list filters), AND-ed with the parent/search scope. */\n filters?: Record<string, unknown>[];\n}\n\ninterface BulkMoveParams {\n fileIds?: number[];\n folderIds?: number[];\n /** `null` moves the items to the root of the Media Library. */\n destinationFolderId: number | null;\n}\n\ntype DataEnvelope<T> = {\n data: T;\n};\n\nconst isDataEnvelope = <T>(response: T | DataEnvelope<T>): response is DataEnvelope<T> =>\n typeof response === 'object' && response !== null && 'data' in response;\n\nconst unwrapData = <T>(response: T | DataEnvelope<T>): T =>\n isDataEnvelope(response) ? response.data : response;\n\nconst foldersApi = uploadApi.injectEndpoints({\n endpoints: (builder) => ({\n getFolders: builder.query<Folder[], GetFoldersParams | void>({\n query: (params = {}) => {\n const { parentId, sort, search, filters = [] } = params as GetFoldersParams;\n\n const queryParams: Record<string, unknown> = {\n // Default matches sidebar FolderTree order (server getStructure uses sortBy('name')).\n sort: sort ?? 'name:ASC',\n populate: { parent: true },\n };\n\n // List filters (dates) apply in BOTH modes — search composes with them,\n // only the parent scope is dropped while searching.\n if (search) {\n // Search is global: the parent filter is dropped so matching folders\n // anywhere in the library surface. The endpoint is unpaginated — it\n // returns every match — so callers can treat the array length as the\n // true total. Bounding it is a separate decision.\n queryParams['_q'] = encodeSearchQuery(search);\n\n if (filters.length > 0) {\n queryParams['filters'] = { $and: [...filters] };\n }\n } else {\n const parentScope =\n parentId != null ? { parent: { id: parentId } } : { parent: { id: { $null: true } } };\n\n queryParams['filters'] = {\n $and: [parentScope, ...filters],\n };\n }\n\n return {\n url: '/upload/folders',\n method: 'GET',\n config: { params: queryParams },\n };\n },\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder', id: 'LIST' },\n ];\n }\n return [{ type: 'Folder', id: 'LIST' }];\n },\n }),\n createFolder: builder.mutation<CreateFolders.Response['data'], CreateFolders.Request['body']>({\n query: (body) => ({\n url: '/upload/folders',\n method: 'POST',\n data: body,\n }),\n transformResponse: (response: CreateFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n updateFolder: builder.mutation<\n UpdateFolder.Response['data'],\n { id: number } & UpdateFolder.Request['body']\n >({\n query: ({ id, ...body }) => ({\n url: `/upload/folders/${id}`,\n method: 'PUT',\n data: body,\n }),\n transformResponse: (response: UpdateFolder.Response) => response.data,\n invalidatesTags: (_result, _error, { id }) => [\n { type: 'Folder', id },\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n /**\n * Hierarchical folder tree used by the FolderTree sidebar. Returned as a\n * single nested array — the server walks the folders table once and\n * assembles parent/child relationships.\n *\n * TODO: filter results like `admin-folder.find` for folder-scoped roles\n * (v1 returns all folders; relies on global `plugin::upload.read`).\n */\n getFolderStructure: builder.query<FolderNode[], void>({\n query: () => ({\n url: '/upload/folder-structure',\n method: 'GET',\n }),\n // TODO: align GetFolderStructure contract with the real /upload/folder-structure\n // envelope and drop this defensive unwrap (data[] vs { data: [] }).\n transformResponse: (response: GetFolderStructure.Response['data']) =>\n ((response as unknown as { data: FolderNode[] })?.data ??\n (response as unknown as FolderNode[]) ??\n []) as FolderNode[],\n providesTags: [{ type: 'Folder', id: 'STRUCTURE' }],\n }),\n /**\n * Flat list of every folder, used to populate the \"Location\" select in the\n * asset details drawer. No parent filter — we want the entire tree in one\n * query so the select can render any destination folder.\n */\n getAllFolders: builder.query<Folder[], void>({\n query: () => ({\n url: '/upload/folders',\n method: 'GET',\n }),\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response ?? []),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder' as const, id: 'LIST' },\n ];\n }\n return [{ type: 'Folder' as const, id: 'LIST' }];\n },\n }),\n getFolder: builder.query<FolderWithCounts, { id: number }>({\n query: ({ id }) => ({\n url: `/upload/folders/${id}`,\n method: 'GET',\n config: {\n params: {\n populate: {\n parent: {\n populate: {\n parent: '*',\n },\n },\n children: { count: true },\n files: { count: true },\n },\n },\n },\n }),\n transformResponse: (response: GetFolder.Response) =>\n response.data as unknown as FolderWithCounts,\n // Also carries the LIST tag so a mutation that changes a folder's file\n // count (upload / delete into it) can refresh the header count by\n // invalidating `{ Folder, LIST }`, without needing the folder id at the\n // mutation site (it's buried in the upload FormData / not passed to the\n // delete).\n providesTags: (_result, _error, { id }) => [\n { type: 'Folder', id },\n { type: 'Folder', id: 'LIST' },\n ],\n }),\n bulkMove: builder.mutation<BulkMoveFolders.Response['data'], BulkMoveParams>({\n query: ({ fileIds = [], folderIds = [], destinationFolderId }) => ({\n url: '/upload/actions/bulk-move',\n method: 'POST',\n data: { fileIds, folderIds, destinationFolderId },\n }),\n transformResponse: (response: BulkMoveFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Asset', id: 'LIST' },\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n }),\n});\n\nexport const {\n useCreateFolderMutation,\n useUpdateFolderMutation,\n useGetFoldersQuery,\n useGetFolderQuery,\n useGetAllFoldersQuery,\n useGetFolderStructureQuery,\n useBulkMoveMutation,\n} = foldersApi;\n"],"names":["isDataEnvelope","response","unwrapData","data","foldersApi","uploadApi","injectEndpoints","endpoints","builder","getFolders","query","params","parentId","sort","search","filters","queryParams","populate","parent","encodeSearchQuery","length","$and","parentScope","id","$null","url","method","config","transformResponse","providesTags","results","map","type","createFolder","mutation","body","invalidatesTags","updateFolder","_result","_error","getFolderStructure","getAllFolders","getFolder","children","count","files","bulkMove","fileIds","folderIds","destinationFolderId","useCreateFolderMutation","useUpdateFolderMutation","useGetFoldersQuery","useGetFolderQuery","useGetAllFoldersQuery","useGetFolderStructureQuery","useBulkMoveMutation"],"mappings":"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"}
|
|
@@ -10,7 +10,10 @@ const foldersApi = uploadApi.injectEndpoints({
|
|
|
10
10
|
const { parentId, sort, search, filters = [] } = params;
|
|
11
11
|
const queryParams = {
|
|
12
12
|
// Default matches sidebar FolderTree order (server getStructure uses sortBy('name')).
|
|
13
|
-
sort: sort ?? 'name:ASC'
|
|
13
|
+
sort: sort ?? 'name:ASC',
|
|
14
|
+
populate: {
|
|
15
|
+
parent: true
|
|
16
|
+
}
|
|
14
17
|
};
|
|
15
18
|
// List filters (dates) apply in BOTH modes — search composes with them,
|
|
16
19
|
// only the parent scope is dropped while searching.
|
|
@@ -94,6 +97,28 @@ const foldersApi = uploadApi.injectEndpoints({
|
|
|
94
97
|
}
|
|
95
98
|
]
|
|
96
99
|
}),
|
|
100
|
+
updateFolder: builder.mutation({
|
|
101
|
+
query: ({ id, ...body })=>({
|
|
102
|
+
url: `/upload/folders/${id}`,
|
|
103
|
+
method: 'PUT',
|
|
104
|
+
data: body
|
|
105
|
+
}),
|
|
106
|
+
transformResponse: (response)=>response.data,
|
|
107
|
+
invalidatesTags: (_result, _error, { id })=>[
|
|
108
|
+
{
|
|
109
|
+
type: 'Folder',
|
|
110
|
+
id
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'Folder',
|
|
114
|
+
id: 'LIST'
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
type: 'Folder',
|
|
118
|
+
id: 'STRUCTURE'
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}),
|
|
97
122
|
/**
|
|
98
123
|
* Hierarchical folder tree used by the FolderTree sidebar. Returned as a
|
|
99
124
|
* single nested array — the server walks the folders table once and
|
|
@@ -170,10 +195,19 @@ const foldersApi = uploadApi.injectEndpoints({
|
|
|
170
195
|
}
|
|
171
196
|
}),
|
|
172
197
|
transformResponse: (response)=>response.data,
|
|
198
|
+
// Also carries the LIST tag so a mutation that changes a folder's file
|
|
199
|
+
// count (upload / delete into it) can refresh the header count by
|
|
200
|
+
// invalidating `{ Folder, LIST }`, without needing the folder id at the
|
|
201
|
+
// mutation site (it's buried in the upload FormData / not passed to the
|
|
202
|
+
// delete).
|
|
173
203
|
providesTags: (_result, _error, { id })=>[
|
|
174
204
|
{
|
|
175
205
|
type: 'Folder',
|
|
176
206
|
id
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
type: 'Folder',
|
|
210
|
+
id: 'LIST'
|
|
177
211
|
}
|
|
178
212
|
]
|
|
179
213
|
}),
|
|
@@ -205,7 +239,7 @@ const foldersApi = uploadApi.injectEndpoints({
|
|
|
205
239
|
})
|
|
206
240
|
})
|
|
207
241
|
});
|
|
208
|
-
const { useCreateFolderMutation, useGetFoldersQuery, useGetFolderQuery, useGetAllFoldersQuery, useGetFolderStructureQuery, useBulkMoveMutation } = foldersApi;
|
|
242
|
+
const { useCreateFolderMutation, useUpdateFolderMutation, useGetFoldersQuery, useGetFolderQuery, useGetAllFoldersQuery, useGetFolderStructureQuery, useBulkMoveMutation } = foldersApi;
|
|
209
243
|
|
|
210
|
-
export { useBulkMoveMutation, useCreateFolderMutation, useGetAllFoldersQuery, useGetFolderQuery, useGetFolderStructureQuery, useGetFoldersQuery };
|
|
244
|
+
export { useBulkMoveMutation, useCreateFolderMutation, useGetAllFoldersQuery, useGetFolderQuery, useGetFolderStructureQuery, useGetFoldersQuery, useUpdateFolderMutation };
|
|
211
245
|
//# sourceMappingURL=folders.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"folders.mjs","sources":["../../../../admin/src/future/services/folders.ts"],"sourcesContent":["import { encodeSearchQuery } from '../utils/searchQueryParam';\n\nimport { uploadApi } from './api';\n\nimport type {\n Folder,\n FolderNode,\n CreateFolders,\n GetFolder,\n GetFolders,\n GetFolderStructure,\n BulkMoveFolders,\n} from '../../../../shared/contracts/folders';\n\nexport type FolderWithCounts = Omit<Folder, 'children' | 'files'> & {\n children?: { count: number };\n files?: { count: number };\n};\n\ninterface GetFoldersParams {\n parentId?: number | null;\n /** Comma-separated rules, e.g. `updatedAt:DESC,name:ASC`. Defaults to alphabetical. */\n sort?: string;\n search?: string;\n /** Extra `filters[$and]` entries (list filters), AND-ed with the parent/search scope. */\n filters?: Record<string, unknown>[];\n}\n\ninterface BulkMoveParams {\n fileIds?: number[];\n folderIds?: number[];\n /** `null` moves the items to the root of the Media Library. */\n destinationFolderId: number | null;\n}\n\ntype DataEnvelope<T> = {\n data: T;\n};\n\nconst isDataEnvelope = <T>(response: T | DataEnvelope<T>): response is DataEnvelope<T> =>\n typeof response === 'object' && response !== null && 'data' in response;\n\nconst unwrapData = <T>(response: T | DataEnvelope<T>): T =>\n isDataEnvelope(response) ? response.data : response;\n\nconst foldersApi = uploadApi.injectEndpoints({\n endpoints: (builder) => ({\n getFolders: builder.query<Folder[], GetFoldersParams | void>({\n query: (params = {}) => {\n const { parentId, sort, search, filters = [] } = params as GetFoldersParams;\n\n const queryParams: Record<string, unknown> = {\n // Default matches sidebar FolderTree order (server getStructure uses sortBy('name')).\n sort: sort ?? 'name:ASC',\n };\n\n // List filters (dates) apply in BOTH modes — search composes with them,\n // only the parent scope is dropped while searching.\n if (search) {\n // Search is global: the parent filter is dropped so matching folders\n // anywhere in the library surface. The endpoint is unpaginated — it\n // returns every match — so callers can treat the array length as the\n // true total. Bounding it is a separate decision.\n queryParams['_q'] = encodeSearchQuery(search);\n\n if (filters.length > 0) {\n queryParams['filters'] = { $and: [...filters] };\n }\n } else {\n const parentScope =\n parentId != null ? { parent: { id: parentId } } : { parent: { id: { $null: true } } };\n\n queryParams['filters'] = {\n $and: [parentScope, ...filters],\n };\n }\n\n return {\n url: '/upload/folders',\n method: 'GET',\n config: { params: queryParams },\n };\n },\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder', id: 'LIST' },\n ];\n }\n return [{ type: 'Folder', id: 'LIST' }];\n },\n }),\n createFolder: builder.mutation<CreateFolders.Response['data'], CreateFolders.Request['body']>({\n query: (body) => ({\n url: '/upload/folders',\n method: 'POST',\n data: body,\n }),\n transformResponse: (response: CreateFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n /**\n * Hierarchical folder tree used by the FolderTree sidebar. Returned as a\n * single nested array — the server walks the folders table once and\n * assembles parent/child relationships.\n *\n * TODO: filter results like `admin-folder.find` for folder-scoped roles\n * (v1 returns all folders; relies on global `plugin::upload.read`).\n */\n getFolderStructure: builder.query<FolderNode[], void>({\n query: () => ({\n url: '/upload/folder-structure',\n method: 'GET',\n }),\n // TODO: align GetFolderStructure contract with the real /upload/folder-structure\n // envelope and drop this defensive unwrap (data[] vs { data: [] }).\n transformResponse: (response: GetFolderStructure.Response['data']) =>\n ((response as unknown as { data: FolderNode[] })?.data ??\n (response as unknown as FolderNode[]) ??\n []) as FolderNode[],\n providesTags: [{ type: 'Folder', id: 'STRUCTURE' }],\n }),\n /**\n * Flat list of every folder, used to populate the \"Location\" select in the\n * asset details drawer. No parent filter — we want the entire tree in one\n * query so the select can render any destination folder.\n */\n getAllFolders: builder.query<Folder[], void>({\n query: () => ({\n url: '/upload/folders',\n method: 'GET',\n }),\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response ?? []),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder' as const, id: 'LIST' },\n ];\n }\n return [{ type: 'Folder' as const, id: 'LIST' }];\n },\n }),\n getFolder: builder.query<FolderWithCounts, { id: number }>({\n query: ({ id }) => ({\n url: `/upload/folders/${id}`,\n method: 'GET',\n config: {\n params: {\n populate: {\n parent: {\n populate: {\n parent: '*',\n },\n },\n children: { count: true },\n files: { count: true },\n },\n },\n },\n }),\n transformResponse: (response: GetFolder.Response) =>\n response.data as unknown as FolderWithCounts,\n providesTags: (_result, _error, { id }) => [{ type: 'Folder', id }],\n }),\n bulkMove: builder.mutation<BulkMoveFolders.Response['data'], BulkMoveParams>({\n query: ({ fileIds = [], folderIds = [], destinationFolderId }) => ({\n url: '/upload/actions/bulk-move',\n method: 'POST',\n data: { fileIds, folderIds, destinationFolderId },\n }),\n transformResponse: (response: BulkMoveFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Asset', id: 'LIST' },\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n }),\n});\n\nexport const {\n useCreateFolderMutation,\n useGetFoldersQuery,\n useGetFolderQuery,\n useGetAllFoldersQuery,\n useGetFolderStructureQuery,\n useBulkMoveMutation,\n} = foldersApi;\n"],"names":["isDataEnvelope","response","unwrapData","data","foldersApi","uploadApi","injectEndpoints","endpoints","builder","getFolders","query","params","parentId","sort","search","filters","queryParams","encodeSearchQuery","length","$and","parentScope","parent","id","$null","url","method","config","transformResponse","providesTags","results","map","type","createFolder","mutation","body","invalidatesTags","getFolderStructure","getAllFolders","getFolder","populate","children","count","files","_result","_error","bulkMove","fileIds","folderIds","destinationFolderId","useCreateFolderMutation","useGetFoldersQuery","useGetFolderQuery","useGetAllFoldersQuery","useGetFolderStructureQuery","useBulkMoveMutation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"folders.mjs","sources":["../../../../admin/src/future/services/folders.ts"],"sourcesContent":["import { encodeSearchQuery } from '../utils/searchQueryParam';\n\nimport { uploadApi } from './api';\n\nimport type {\n Folder,\n FolderNode,\n CreateFolders,\n GetFolder,\n GetFolders,\n GetFolderStructure,\n BulkMoveFolders,\n UpdateFolder,\n} from '../../../../shared/contracts/folders';\n\nexport type FolderWithCounts = Omit<Folder, 'children' | 'files'> & {\n children?: { count: number };\n files?: { count: number };\n};\n\ninterface GetFoldersParams {\n parentId?: number | null;\n /** Comma-separated rules, e.g. `updatedAt:DESC,name:ASC`. Defaults to alphabetical. */\n sort?: string;\n search?: string;\n /** Extra `filters[$and]` entries (list filters), AND-ed with the parent/search scope. */\n filters?: Record<string, unknown>[];\n}\n\ninterface BulkMoveParams {\n fileIds?: number[];\n folderIds?: number[];\n /** `null` moves the items to the root of the Media Library. */\n destinationFolderId: number | null;\n}\n\ntype DataEnvelope<T> = {\n data: T;\n};\n\nconst isDataEnvelope = <T>(response: T | DataEnvelope<T>): response is DataEnvelope<T> =>\n typeof response === 'object' && response !== null && 'data' in response;\n\nconst unwrapData = <T>(response: T | DataEnvelope<T>): T =>\n isDataEnvelope(response) ? response.data : response;\n\nconst foldersApi = uploadApi.injectEndpoints({\n endpoints: (builder) => ({\n getFolders: builder.query<Folder[], GetFoldersParams | void>({\n query: (params = {}) => {\n const { parentId, sort, search, filters = [] } = params as GetFoldersParams;\n\n const queryParams: Record<string, unknown> = {\n // Default matches sidebar FolderTree order (server getStructure uses sortBy('name')).\n sort: sort ?? 'name:ASC',\n populate: { parent: true },\n };\n\n // List filters (dates) apply in BOTH modes — search composes with them,\n // only the parent scope is dropped while searching.\n if (search) {\n // Search is global: the parent filter is dropped so matching folders\n // anywhere in the library surface. The endpoint is unpaginated — it\n // returns every match — so callers can treat the array length as the\n // true total. Bounding it is a separate decision.\n queryParams['_q'] = encodeSearchQuery(search);\n\n if (filters.length > 0) {\n queryParams['filters'] = { $and: [...filters] };\n }\n } else {\n const parentScope =\n parentId != null ? { parent: { id: parentId } } : { parent: { id: { $null: true } } };\n\n queryParams['filters'] = {\n $and: [parentScope, ...filters],\n };\n }\n\n return {\n url: '/upload/folders',\n method: 'GET',\n config: { params: queryParams },\n };\n },\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder', id: 'LIST' },\n ];\n }\n return [{ type: 'Folder', id: 'LIST' }];\n },\n }),\n createFolder: builder.mutation<CreateFolders.Response['data'], CreateFolders.Request['body']>({\n query: (body) => ({\n url: '/upload/folders',\n method: 'POST',\n data: body,\n }),\n transformResponse: (response: CreateFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n updateFolder: builder.mutation<\n UpdateFolder.Response['data'],\n { id: number } & UpdateFolder.Request['body']\n >({\n query: ({ id, ...body }) => ({\n url: `/upload/folders/${id}`,\n method: 'PUT',\n data: body,\n }),\n transformResponse: (response: UpdateFolder.Response) => response.data,\n invalidatesTags: (_result, _error, { id }) => [\n { type: 'Folder', id },\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n /**\n * Hierarchical folder tree used by the FolderTree sidebar. Returned as a\n * single nested array — the server walks the folders table once and\n * assembles parent/child relationships.\n *\n * TODO: filter results like `admin-folder.find` for folder-scoped roles\n * (v1 returns all folders; relies on global `plugin::upload.read`).\n */\n getFolderStructure: builder.query<FolderNode[], void>({\n query: () => ({\n url: '/upload/folder-structure',\n method: 'GET',\n }),\n // TODO: align GetFolderStructure contract with the real /upload/folder-structure\n // envelope and drop this defensive unwrap (data[] vs { data: [] }).\n transformResponse: (response: GetFolderStructure.Response['data']) =>\n ((response as unknown as { data: FolderNode[] })?.data ??\n (response as unknown as FolderNode[]) ??\n []) as FolderNode[],\n providesTags: [{ type: 'Folder', id: 'STRUCTURE' }],\n }),\n /**\n * Flat list of every folder, used to populate the \"Location\" select in the\n * asset details drawer. No parent filter — we want the entire tree in one\n * query so the select can render any destination folder.\n */\n getAllFolders: builder.query<Folder[], void>({\n query: () => ({\n url: '/upload/folders',\n method: 'GET',\n }),\n transformResponse: (response: GetFolders.Response['data']) =>\n unwrapData<GetFolders.Response['data']>(response ?? []),\n providesTags: (results) => {\n if (results) {\n return [\n ...results.map(({ id }) => ({ type: 'Folder' as const, id })),\n { type: 'Folder' as const, id: 'LIST' },\n ];\n }\n return [{ type: 'Folder' as const, id: 'LIST' }];\n },\n }),\n getFolder: builder.query<FolderWithCounts, { id: number }>({\n query: ({ id }) => ({\n url: `/upload/folders/${id}`,\n method: 'GET',\n config: {\n params: {\n populate: {\n parent: {\n populate: {\n parent: '*',\n },\n },\n children: { count: true },\n files: { count: true },\n },\n },\n },\n }),\n transformResponse: (response: GetFolder.Response) =>\n response.data as unknown as FolderWithCounts,\n // Also carries the LIST tag so a mutation that changes a folder's file\n // count (upload / delete into it) can refresh the header count by\n // invalidating `{ Folder, LIST }`, without needing the folder id at the\n // mutation site (it's buried in the upload FormData / not passed to the\n // delete).\n providesTags: (_result, _error, { id }) => [\n { type: 'Folder', id },\n { type: 'Folder', id: 'LIST' },\n ],\n }),\n bulkMove: builder.mutation<BulkMoveFolders.Response['data'], BulkMoveParams>({\n query: ({ fileIds = [], folderIds = [], destinationFolderId }) => ({\n url: '/upload/actions/bulk-move',\n method: 'POST',\n data: { fileIds, folderIds, destinationFolderId },\n }),\n transformResponse: (response: BulkMoveFolders.Response) => response.data,\n invalidatesTags: [\n { type: 'Asset', id: 'LIST' },\n { type: 'Folder', id: 'LIST' },\n { type: 'Folder', id: 'STRUCTURE' },\n ],\n }),\n }),\n});\n\nexport const {\n useCreateFolderMutation,\n useUpdateFolderMutation,\n useGetFoldersQuery,\n useGetFolderQuery,\n useGetAllFoldersQuery,\n useGetFolderStructureQuery,\n useBulkMoveMutation,\n} = foldersApi;\n"],"names":["isDataEnvelope","response","unwrapData","data","foldersApi","uploadApi","injectEndpoints","endpoints","builder","getFolders","query","params","parentId","sort","search","filters","queryParams","populate","parent","encodeSearchQuery","length","$and","parentScope","id","$null","url","method","config","transformResponse","providesTags","results","map","type","createFolder","mutation","body","invalidatesTags","updateFolder","_result","_error","getFolderStructure","getAllFolders","getFolder","children","count","files","bulkMove","fileIds","folderIds","destinationFolderId","useCreateFolderMutation","useUpdateFolderMutation","useGetFoldersQuery","useGetFolderQuery","useGetAllFoldersQuery","useGetFolderStructureQuery","useBulkMoveMutation"],"mappings":"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"}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var itemLocations = require('./itemLocations.js');
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Reconstruct the drag set from a bulk-actions selection so the dialog can feed
|
|
5
7
|
* the exact same `DragItemData[]` into `computeValidDropTargets` / the canonical
|
|
6
8
|
* `canDropItemOnFolder` predicate that pointer drag uses.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* Each item's location comes from the loaded row, not from the folder currently
|
|
11
|
+
* open: search results are global, so a selected item can live anywhere.
|
|
10
12
|
* Names are irrelevant to drop validation, so they are left empty.
|
|
11
|
-
*/ const buildDragSetFromSelection = (selectedIds, selectedFolderIds,
|
|
13
|
+
*/ const buildDragSetFromSelection = (selectedIds, selectedFolderIds, locations, fallbackFolderId)=>{
|
|
12
14
|
const items = [];
|
|
13
15
|
selectedIds.forEach((id)=>{
|
|
14
16
|
items.push({
|
|
15
17
|
kind: 'file',
|
|
16
18
|
id,
|
|
17
19
|
name: '',
|
|
18
|
-
folderId:
|
|
20
|
+
folderId: itemLocations.locateItem(locations, 'file', id, fallbackFolderId)
|
|
19
21
|
});
|
|
20
22
|
});
|
|
21
23
|
selectedFolderIds.forEach((id)=>{
|
|
@@ -23,7 +25,7 @@
|
|
|
23
25
|
kind: 'folder',
|
|
24
26
|
id,
|
|
25
27
|
name: '',
|
|
26
|
-
parentId:
|
|
28
|
+
parentId: itemLocations.locateItem(locations, 'folder', id, fallbackFolderId)
|
|
27
29
|
});
|
|
28
30
|
});
|
|
29
31
|
return items;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildDragSetFromSelection.js","sources":["../../../../admin/src/future/utils/buildDragSetFromSelection.ts"],"sourcesContent":["import type { DragItemData } from '../types/dnd';\n\n/**\n * Reconstruct the drag set from a bulk-actions selection so the dialog can feed\n * the exact same `DragItemData[]` into `computeValidDropTargets` / the canonical\n * `canDropItemOnFolder` predicate that pointer drag uses.\n *\n *
|
|
1
|
+
{"version":3,"file":"buildDragSetFromSelection.js","sources":["../../../../admin/src/future/utils/buildDragSetFromSelection.ts"],"sourcesContent":["import { locateItem, type ItemLocations } from './itemLocations';\n\nimport type { DragItemData } from '../types/dnd';\n\n/**\n * Reconstruct the drag set from a bulk-actions selection so the dialog can feed\n * the exact same `DragItemData[]` into `computeValidDropTargets` / the canonical\n * `canDropItemOnFolder` predicate that pointer drag uses.\n *\n * Each item's location comes from the loaded row, not from the folder currently\n * open: search results are global, so a selected item can live anywhere.\n * Names are irrelevant to drop validation, so they are left empty.\n */\nexport const buildDragSetFromSelection = (\n selectedIds: ReadonlySet<number>,\n selectedFolderIds: ReadonlySet<number>,\n locations: ItemLocations,\n fallbackFolderId: number | null\n): DragItemData[] => {\n const items: DragItemData[] = [];\n\n selectedIds.forEach((id) => {\n items.push({\n kind: 'file',\n id,\n name: '',\n folderId: locateItem(locations, 'file', id, fallbackFolderId),\n });\n });\n\n selectedFolderIds.forEach((id) => {\n items.push({\n kind: 'folder',\n id,\n name: '',\n parentId: locateItem(locations, 'folder', id, fallbackFolderId),\n });\n });\n\n return items;\n};\n"],"names":["buildDragSetFromSelection","selectedIds","selectedFolderIds","locations","fallbackFolderId","items","forEach","id","push","kind","name","folderId","locateItem","parentId"],"mappings":";;;;AAIA;;;;;;;;AAQC,IACM,MAAMA,yBAAAA,GAA4B,CACvCC,WAAAA,EACAC,mBACAC,SAAAA,EACAC,gBAAAA,GAAAA;AAEA,IAAA,MAAMC,QAAwB,EAAE;IAEhCJ,WAAAA,CAAYK,OAAO,CAAC,CAACC,EAAAA,GAAAA;AACnBF,QAAAA,KAAAA,CAAMG,IAAI,CAAC;YACTC,IAAAA,EAAM,MAAA;AACNF,YAAAA,EAAAA;YACAG,IAAAA,EAAM,EAAA;YACNC,QAAAA,EAAUC,wBAAAA,CAAWT,SAAAA,EAAW,MAAA,EAAQI,EAAAA,EAAIH,gBAAAA;AAC9C,SAAA,CAAA;AACF,IAAA,CAAA,CAAA;IAEAF,iBAAAA,CAAkBI,OAAO,CAAC,CAACC,EAAAA,GAAAA;AACzBF,QAAAA,KAAAA,CAAMG,IAAI,CAAC;YACTC,IAAAA,EAAM,QAAA;AACNF,YAAAA,EAAAA;YACAG,IAAAA,EAAM,EAAA;YACNG,QAAAA,EAAUD,wBAAAA,CAAWT,SAAAA,EAAW,QAAA,EAAUI,EAAAA,EAAIH,gBAAAA;AAChD,SAAA,CAAA;AACF,IAAA,CAAA,CAAA;IAEA,OAAOC,KAAAA;AACT;;;;"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
+
import { locateItem } from './itemLocations.mjs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Reconstruct the drag set from a bulk-actions selection so the dialog can feed
|
|
3
5
|
* the exact same `DragItemData[]` into `computeValidDropTargets` / the canonical
|
|
4
6
|
* `canDropItemOnFolder` predicate that pointer drag uses.
|
|
5
7
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
+
* Each item's location comes from the loaded row, not from the folder currently
|
|
9
|
+
* open: search results are global, so a selected item can live anywhere.
|
|
8
10
|
* Names are irrelevant to drop validation, so they are left empty.
|
|
9
|
-
*/ const buildDragSetFromSelection = (selectedIds, selectedFolderIds,
|
|
11
|
+
*/ const buildDragSetFromSelection = (selectedIds, selectedFolderIds, locations, fallbackFolderId)=>{
|
|
10
12
|
const items = [];
|
|
11
13
|
selectedIds.forEach((id)=>{
|
|
12
14
|
items.push({
|
|
13
15
|
kind: 'file',
|
|
14
16
|
id,
|
|
15
17
|
name: '',
|
|
16
|
-
folderId:
|
|
18
|
+
folderId: locateItem(locations, 'file', id, fallbackFolderId)
|
|
17
19
|
});
|
|
18
20
|
});
|
|
19
21
|
selectedFolderIds.forEach((id)=>{
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
kind: 'folder',
|
|
22
24
|
id,
|
|
23
25
|
name: '',
|
|
24
|
-
parentId:
|
|
26
|
+
parentId: locateItem(locations, 'folder', id, fallbackFolderId)
|
|
25
27
|
});
|
|
26
28
|
});
|
|
27
29
|
return items;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildDragSetFromSelection.mjs","sources":["../../../../admin/src/future/utils/buildDragSetFromSelection.ts"],"sourcesContent":["import type { DragItemData } from '../types/dnd';\n\n/**\n * Reconstruct the drag set from a bulk-actions selection so the dialog can feed\n * the exact same `DragItemData[]` into `computeValidDropTargets` / the canonical\n * `canDropItemOnFolder` predicate that pointer drag uses.\n *\n *
|
|
1
|
+
{"version":3,"file":"buildDragSetFromSelection.mjs","sources":["../../../../admin/src/future/utils/buildDragSetFromSelection.ts"],"sourcesContent":["import { locateItem, type ItemLocations } from './itemLocations';\n\nimport type { DragItemData } from '../types/dnd';\n\n/**\n * Reconstruct the drag set from a bulk-actions selection so the dialog can feed\n * the exact same `DragItemData[]` into `computeValidDropTargets` / the canonical\n * `canDropItemOnFolder` predicate that pointer drag uses.\n *\n * Each item's location comes from the loaded row, not from the folder currently\n * open: search results are global, so a selected item can live anywhere.\n * Names are irrelevant to drop validation, so they are left empty.\n */\nexport const buildDragSetFromSelection = (\n selectedIds: ReadonlySet<number>,\n selectedFolderIds: ReadonlySet<number>,\n locations: ItemLocations,\n fallbackFolderId: number | null\n): DragItemData[] => {\n const items: DragItemData[] = [];\n\n selectedIds.forEach((id) => {\n items.push({\n kind: 'file',\n id,\n name: '',\n folderId: locateItem(locations, 'file', id, fallbackFolderId),\n });\n });\n\n selectedFolderIds.forEach((id) => {\n items.push({\n kind: 'folder',\n id,\n name: '',\n parentId: locateItem(locations, 'folder', id, fallbackFolderId),\n });\n });\n\n return items;\n};\n"],"names":["buildDragSetFromSelection","selectedIds","selectedFolderIds","locations","fallbackFolderId","items","forEach","id","push","kind","name","folderId","locateItem","parentId"],"mappings":";;AAIA;;;;;;;;AAQC,IACM,MAAMA,yBAAAA,GAA4B,CACvCC,WAAAA,EACAC,mBACAC,SAAAA,EACAC,gBAAAA,GAAAA;AAEA,IAAA,MAAMC,QAAwB,EAAE;IAEhCJ,WAAAA,CAAYK,OAAO,CAAC,CAACC,EAAAA,GAAAA;AACnBF,QAAAA,KAAAA,CAAMG,IAAI,CAAC;YACTC,IAAAA,EAAM,MAAA;AACNF,YAAAA,EAAAA;YACAG,IAAAA,EAAM,EAAA;YACNC,QAAAA,EAAUC,UAAAA,CAAWT,SAAAA,EAAW,MAAA,EAAQI,EAAAA,EAAIH,gBAAAA;AAC9C,SAAA,CAAA;AACF,IAAA,CAAA,CAAA;IAEAF,iBAAAA,CAAkBI,OAAO,CAAC,CAACC,EAAAA,GAAAA;AACzBF,QAAAA,KAAAA,CAAMG,IAAI,CAAC;YACTC,IAAAA,EAAM,QAAA;AACNF,YAAAA,EAAAA;YACAG,IAAAA,EAAM,EAAA;YACNG,QAAAA,EAAUD,UAAAA,CAAWT,SAAAA,EAAW,QAAA,EAAUI,EAAAA,EAAIH,gBAAAA;AAChD,SAAA,CAAA;AACF,IAAA,CAAA,CAAA;IAEA,OAAOC,KAAAA;AACT;;;;"}
|
|
@@ -6,7 +6,17 @@ var translations = require('./translations.js');
|
|
|
6
6
|
* Single source of truth for the bulk-move success wording. Both the DnD drop
|
|
7
7
|
* and the BulkMoveDialog format the toast (and DnD live-region announcement)
|
|
8
8
|
* through here so the two paths stay identical for the same move.
|
|
9
|
-
*/ const formatMoveSuccessMessage = ({ formatMessage, count, source, destination })=>
|
|
9
|
+
*/ const formatMoveSuccessMessage = ({ formatMessage, count, source, destination })=>{
|
|
10
|
+
if (source === null) {
|
|
11
|
+
return formatMessage({
|
|
12
|
+
id: translations.getTranslationKey('list.bulk-actions.move.success-multiple-sources'),
|
|
13
|
+
defaultMessage: '{count, plural, =1 {# element has} other {# elements have}} been moved to {destination}'
|
|
14
|
+
}, {
|
|
15
|
+
count,
|
|
16
|
+
destination
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return formatMessage({
|
|
10
20
|
id: translations.getTranslationKey('list.bulk-actions.move.success'),
|
|
11
21
|
defaultMessage: '{count, plural, =1 {# element has} other {# elements have}} been moved from {source} to {destination}'
|
|
12
22
|
}, {
|
|
@@ -14,6 +24,7 @@ var translations = require('./translations.js');
|
|
|
14
24
|
source,
|
|
15
25
|
destination
|
|
16
26
|
});
|
|
27
|
+
};
|
|
17
28
|
|
|
18
29
|
exports.formatMoveSuccessMessage = formatMoveSuccessMessage;
|
|
19
30
|
//# sourceMappingURL=formatMoveSuccessMessage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatMoveSuccessMessage.js","sources":["../../../../admin/src/future/utils/formatMoveSuccessMessage.ts"],"sourcesContent":["import { getTranslationKey } from './translations';\n\nimport type { IntlShape } from 'react-intl';\n\ninterface FormatMoveSuccessArgs {\n formatMessage: IntlShape['formatMessage'];\n count: number;\n source: string;\n destination: string;\n}\n\n/**\n * Single source of truth for the bulk-move success wording. Both the DnD drop\n * and the BulkMoveDialog format the toast (and DnD live-region announcement)\n * through here so the two paths stay identical for the same move.\n */\nexport const formatMoveSuccessMessage = ({\n formatMessage,\n count,\n source,\n destination,\n}: FormatMoveSuccessArgs): string
|
|
1
|
+
{"version":3,"file":"formatMoveSuccessMessage.js","sources":["../../../../admin/src/future/utils/formatMoveSuccessMessage.ts"],"sourcesContent":["import { getTranslationKey } from './translations';\n\nimport type { IntlShape } from 'react-intl';\n\ninterface FormatMoveSuccessArgs {\n formatMessage: IntlShape['formatMessage'];\n count: number;\n /**\n * Leaf name of the folder the items came from, or `null` when the move spans\n * several source folders and no single one can be named — a global-search\n * selection can hold items from anywhere. The wording then omits the source\n * rather than naming one folder and implying the rest came from it too.\n */\n source: string | null;\n destination: string;\n}\n\n/**\n * Single source of truth for the bulk-move success wording. Both the DnD drop\n * and the BulkMoveDialog format the toast (and DnD live-region announcement)\n * through here so the two paths stay identical for the same move.\n */\nexport const formatMoveSuccessMessage = ({\n formatMessage,\n count,\n source,\n destination,\n}: FormatMoveSuccessArgs): string => {\n if (source === null) {\n return formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.move.success-multiple-sources'),\n defaultMessage:\n '{count, plural, =1 {# element has} other {# elements have}} been moved to {destination}',\n },\n { count, destination }\n );\n }\n\n return formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.move.success'),\n defaultMessage:\n '{count, plural, =1 {# element has} other {# elements have}} been moved from {source} to {destination}',\n },\n { count, source, destination }\n );\n};\n"],"names":["formatMoveSuccessMessage","formatMessage","count","source","destination","id","getTranslationKey","defaultMessage"],"mappings":";;;;AAiBA;;;;AAIC,IACM,MAAMA,wBAAAA,GAA2B,CAAC,EACvCC,aAAa,EACbC,KAAK,EACLC,MAAM,EACNC,WAAW,EACW,GAAA;AACtB,IAAA,IAAID,WAAW,IAAA,EAAM;AACnB,QAAA,OAAOF,aAAAA,CACL;AACEI,YAAAA,EAAAA,EAAIC,8BAAAA,CAAkB,iDAAA,CAAA;YACtBC,cAAAA,EACE;SACJ,EACA;AAAEL,YAAAA,KAAAA;AAAOE,YAAAA;AAAY,SAAA,CAAA;AAEzB,IAAA;AAEA,IAAA,OAAOH,aAAAA,CACL;AACEI,QAAAA,EAAAA,EAAIC,8BAAAA,CAAkB,gCAAA,CAAA;QACtBC,cAAAA,EACE;KACJ,EACA;AAAEL,QAAAA,KAAAA;AAAOC,QAAAA,MAAAA;AAAQC,QAAAA;AAAY,KAAA,CAAA;AAEjC;;;;"}
|
|
@@ -4,7 +4,17 @@ import { getTranslationKey } from './translations.mjs';
|
|
|
4
4
|
* Single source of truth for the bulk-move success wording. Both the DnD drop
|
|
5
5
|
* and the BulkMoveDialog format the toast (and DnD live-region announcement)
|
|
6
6
|
* through here so the two paths stay identical for the same move.
|
|
7
|
-
*/ const formatMoveSuccessMessage = ({ formatMessage, count, source, destination })=>
|
|
7
|
+
*/ const formatMoveSuccessMessage = ({ formatMessage, count, source, destination })=>{
|
|
8
|
+
if (source === null) {
|
|
9
|
+
return formatMessage({
|
|
10
|
+
id: getTranslationKey('list.bulk-actions.move.success-multiple-sources'),
|
|
11
|
+
defaultMessage: '{count, plural, =1 {# element has} other {# elements have}} been moved to {destination}'
|
|
12
|
+
}, {
|
|
13
|
+
count,
|
|
14
|
+
destination
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return formatMessage({
|
|
8
18
|
id: getTranslationKey('list.bulk-actions.move.success'),
|
|
9
19
|
defaultMessage: '{count, plural, =1 {# element has} other {# elements have}} been moved from {source} to {destination}'
|
|
10
20
|
}, {
|
|
@@ -12,6 +22,7 @@ import { getTranslationKey } from './translations.mjs';
|
|
|
12
22
|
source,
|
|
13
23
|
destination
|
|
14
24
|
});
|
|
25
|
+
};
|
|
15
26
|
|
|
16
27
|
export { formatMoveSuccessMessage };
|
|
17
28
|
//# sourceMappingURL=formatMoveSuccessMessage.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatMoveSuccessMessage.mjs","sources":["../../../../admin/src/future/utils/formatMoveSuccessMessage.ts"],"sourcesContent":["import { getTranslationKey } from './translations';\n\nimport type { IntlShape } from 'react-intl';\n\ninterface FormatMoveSuccessArgs {\n formatMessage: IntlShape['formatMessage'];\n count: number;\n source: string;\n destination: string;\n}\n\n/**\n * Single source of truth for the bulk-move success wording. Both the DnD drop\n * and the BulkMoveDialog format the toast (and DnD live-region announcement)\n * through here so the two paths stay identical for the same move.\n */\nexport const formatMoveSuccessMessage = ({\n formatMessage,\n count,\n source,\n destination,\n}: FormatMoveSuccessArgs): string
|
|
1
|
+
{"version":3,"file":"formatMoveSuccessMessage.mjs","sources":["../../../../admin/src/future/utils/formatMoveSuccessMessage.ts"],"sourcesContent":["import { getTranslationKey } from './translations';\n\nimport type { IntlShape } from 'react-intl';\n\ninterface FormatMoveSuccessArgs {\n formatMessage: IntlShape['formatMessage'];\n count: number;\n /**\n * Leaf name of the folder the items came from, or `null` when the move spans\n * several source folders and no single one can be named — a global-search\n * selection can hold items from anywhere. The wording then omits the source\n * rather than naming one folder and implying the rest came from it too.\n */\n source: string | null;\n destination: string;\n}\n\n/**\n * Single source of truth for the bulk-move success wording. Both the DnD drop\n * and the BulkMoveDialog format the toast (and DnD live-region announcement)\n * through here so the two paths stay identical for the same move.\n */\nexport const formatMoveSuccessMessage = ({\n formatMessage,\n count,\n source,\n destination,\n}: FormatMoveSuccessArgs): string => {\n if (source === null) {\n return formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.move.success-multiple-sources'),\n defaultMessage:\n '{count, plural, =1 {# element has} other {# elements have}} been moved to {destination}',\n },\n { count, destination }\n );\n }\n\n return formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.move.success'),\n defaultMessage:\n '{count, plural, =1 {# element has} other {# elements have}} been moved from {source} to {destination}',\n },\n { count, source, destination }\n );\n};\n"],"names":["formatMoveSuccessMessage","formatMessage","count","source","destination","id","getTranslationKey","defaultMessage"],"mappings":";;AAiBA;;;;AAIC,IACM,MAAMA,wBAAAA,GAA2B,CAAC,EACvCC,aAAa,EACbC,KAAK,EACLC,MAAM,EACNC,WAAW,EACW,GAAA;AACtB,IAAA,IAAID,WAAW,IAAA,EAAM;AACnB,QAAA,OAAOF,aAAAA,CACL;AACEI,YAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,iDAAA,CAAA;YACtBC,cAAAA,EACE;SACJ,EACA;AAAEL,YAAAA,KAAAA;AAAOE,YAAAA;AAAY,SAAA,CAAA;AAEzB,IAAA;AAEA,IAAA,OAAOH,aAAAA,CACL;AACEI,QAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,gCAAA,CAAA;QACtBC,cAAAA,EACE;KACJ,EACA;AAAEL,QAAAA,KAAAA;AAAOC,QAAAA,MAAAA;AAAQC,QAAAA;AAAY,KAAA,CAAA;AAEjC;;;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Normalise a to-one relation down to its id.
|
|
5
|
+
*
|
|
6
|
+
* The contracts type `File['folder']` and `Folder['parent']` as ids, but the
|
|
7
|
+
* admin populates both (`populate: { folder: true }` on `/upload/files`,
|
|
8
|
+
* `populate: { parent: true }` on `/upload/folders`), so the wire value is an
|
|
9
|
+
* object. Only the id is ever read — move validation compares locations by id.
|
|
10
|
+
*/ const getRelationId = (relation)=>{
|
|
11
|
+
if (relation == null) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
if (typeof relation === 'object') {
|
|
15
|
+
return relation.id ?? null;
|
|
16
|
+
}
|
|
17
|
+
if (typeof relation === 'number') {
|
|
18
|
+
return relation;
|
|
19
|
+
}
|
|
20
|
+
return Number(relation) || null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
exports.getRelationId = getRelationId;
|
|
24
|
+
//# sourceMappingURL=getRelationId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getRelationId.js","sources":["../../../../admin/src/future/utils/getRelationId.ts"],"sourcesContent":["/**\n * Normalise a to-one relation down to its id.\n *\n * The contracts type `File['folder']` and `Folder['parent']` as ids, but the\n * admin populates both (`populate: { folder: true }` on `/upload/files`,\n * `populate: { parent: true }` on `/upload/folders`), so the wire value is an\n * object. Only the id is ever read — move validation compares locations by id.\n */\nexport const getRelationId = (\n relation: number | string | { id?: number } | null | undefined\n): number | null => {\n if (relation == null) {\n return null;\n }\n\n if (typeof relation === 'object') {\n return relation.id ?? null;\n }\n\n if (typeof relation === 'number') {\n return relation;\n }\n\n return Number(relation) || null;\n};\n"],"names":["getRelationId","relation","id","Number"],"mappings":";;AAAA;;;;;;;IAQO,MAAMA,aAAAA,GAAgB,CAC3BC,QAAAA,GAAAA;AAEA,IAAA,IAAIA,YAAY,IAAA,EAAM;QACpB,OAAO,IAAA;AACT,IAAA;IAEA,IAAI,OAAOA,aAAa,QAAA,EAAU;QAChC,OAAOA,QAAAA,CAASC,EAAE,IAAI,IAAA;AACxB,IAAA;IAEA,IAAI,OAAOD,aAAa,QAAA,EAAU;QAChC,OAAOA,QAAAA;AACT,IAAA;AAEA,IAAA,OAAOE,OAAOF,QAAAA,CAAAA,IAAa,IAAA;AAC7B;;;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalise a to-one relation down to its id.
|
|
3
|
+
*
|
|
4
|
+
* The contracts type `File['folder']` and `Folder['parent']` as ids, but the
|
|
5
|
+
* admin populates both (`populate: { folder: true }` on `/upload/files`,
|
|
6
|
+
* `populate: { parent: true }` on `/upload/folders`), so the wire value is an
|
|
7
|
+
* object. Only the id is ever read — move validation compares locations by id.
|
|
8
|
+
*/ const getRelationId = (relation)=>{
|
|
9
|
+
if (relation == null) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
if (typeof relation === 'object') {
|
|
13
|
+
return relation.id ?? null;
|
|
14
|
+
}
|
|
15
|
+
if (typeof relation === 'number') {
|
|
16
|
+
return relation;
|
|
17
|
+
}
|
|
18
|
+
return Number(relation) || null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { getRelationId };
|
|
22
|
+
//# sourceMappingURL=getRelationId.mjs.map
|