@strapi/upload 5.51.2 → 5.52.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/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/components/TruncatedText.js +76 -0
- package/dist/admin/future/components/TruncatedText.js.map +1 -0
- package/dist/admin/future/components/TruncatedText.mjs +74 -0
- package/dist/admin/future/components/TruncatedText.mjs.map +1 -0
- 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/hooks/useTracking.js +57 -0
- package/dist/admin/future/hooks/useTracking.js.map +1 -0
- package/dist/admin/future/hooks/useTracking.mjs +53 -0
- package/dist/admin/future/hooks/useTracking.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js +328 -139
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +332 -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 +328 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +326 -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 +74 -53
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +74 -54
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +92 -28
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +94 -30
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +26 -4
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +27 -5
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +172 -60
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +175 -63
- 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 +259 -63
- package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +262 -66
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js +146 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs +144 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.js → FolderFormDialog.js} +62 -16
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.mjs → FolderFormDialog.mjs} +64 -18
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +132 -229
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +135 -232
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.js +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +5 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +6 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.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/pages/Assets/utils/selection.js +17 -0
- package/dist/admin/future/pages/Assets/utils/selection.js.map +1 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs +17 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs.map +1 -1
- package/dist/admin/future/services/api.js +31 -8
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +31 -8
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +22 -23
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +22 -23
- 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/hooks/useAIMetadataJob.js +1 -1
- package/dist/admin/hooks/useAIMetadataJob.js.map +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs.map +1 -1
- 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/pages/SettingsPage/SettingsPage.js +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.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/components/TruncatedText.d.ts +32 -0
- package/dist/admin/src/future/hooks/useAIMetadataEnabled.d.ts +26 -0
- package/dist/admin/src/future/hooks/useTracking.d.ts +29 -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 +26 -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 +21 -0
- package/dist/admin/src/future/pages/Assets/components/FolderFormDialog.d.ts +16 -0
- package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +2 -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/pages/Assets/utils/selection.d.ts +10 -0
- package/dist/admin/src/future/services/api.d.ts +6 -7
- 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/controllers/admin-file.js +27 -9
- package/dist/server/controllers/admin-file.js.map +1 -1
- package/dist/server/controllers/admin-file.mjs +27 -9
- package/dist/server/controllers/admin-file.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +24 -8
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +24 -8
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/routes/admin.js +41 -21
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +41 -21
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/services/ai-metadata.js.map +1 -1
- package/dist/server/services/ai-metadata.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/controllers/admin-file.d.ts +29 -8
- package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +20 -4
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +4 -4
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/ai-metadata.d.ts +2 -2
- package/dist/server/src/services/ai-metadata.d.ts.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/dist/shared/contracts/ai-metadata-jobs.d.ts +10 -32
- package/dist/shared/contracts/ai-metadata-jobs.d.ts.map +1 -1
- package/dist/shared/contracts/files.d.ts +10 -10
- package/dist/shared/contracts/files.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
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Folder } from '../../../../../../shared/contracts/folders';
|
|
2
|
+
import type { DragFolderData } from '../../../types/dnd';
|
|
3
|
+
interface FolderActionsMenuProps {
|
|
4
|
+
folder: Folder;
|
|
5
|
+
/** Drag data for this folder, so the move dialog validates against its real parent. */
|
|
6
|
+
dragData: DragFolderData;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The "..." menu on a folder row/card. Always acts on that one folder, whatever
|
|
10
|
+
* the current multi-selection is (the bulk actions bar is the selection-scoped
|
|
11
|
+
* affordance). It reuses the shared move and delete dialogs, which mount only
|
|
12
|
+
* while open.
|
|
13
|
+
*
|
|
14
|
+
* A successful move or delete deselects this one folder and leaves the rest of
|
|
15
|
+
* the selection intact: they only invalidate RTK tags, so without it a
|
|
16
|
+
* `folder:<id>` key for a folder that no longer lives where the selection thinks
|
|
17
|
+
* it does would linger. A rename leaves the id valid and the folder in place, so
|
|
18
|
+
* it touches the selection not at all.
|
|
19
|
+
*/
|
|
20
|
+
export declare const FolderActionsMenu: ({ folder, dragData }: FolderActionsMenuProps) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface FolderFormDialogBaseProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
/** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */
|
|
5
|
+
parentFolderId: number | null;
|
|
6
|
+
}
|
|
7
|
+
type FolderFormDialogProps = FolderFormDialogBaseProps & ({
|
|
8
|
+
mode: 'create';
|
|
9
|
+
parentFolderName: string;
|
|
10
|
+
} | {
|
|
11
|
+
mode: 'rename';
|
|
12
|
+
folderId: number;
|
|
13
|
+
initialName: string;
|
|
14
|
+
});
|
|
15
|
+
export declare const FolderFormDialog: (props: FolderFormDialogProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
@@ -27,6 +27,8 @@ export interface AssetSelection {
|
|
|
27
27
|
selectRange: (orderedKeys: ItemKey[], targetKey: ItemKey) => void;
|
|
28
28
|
/** Header checkbox — selects every rendered item (folders and assets). */
|
|
29
29
|
selectAll: (orderedKeys: ItemKey[]) => void;
|
|
30
|
+
/** Row-level "..." menu — drops one key when its item leaves the list (move, delete). */
|
|
31
|
+
deselect: (key: ItemKey) => void;
|
|
30
32
|
/** Close button / folder navigation / list-identity changes. */
|
|
31
33
|
clear: () => void;
|
|
32
34
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Which assets have a long-running mutation in flight, so the list can show it
|
|
4
|
+
* on the item itself.
|
|
5
|
+
*
|
|
6
|
+
* The mutation stays where it is triggered — the row's "..." menu — but the
|
|
7
|
+
* feedback has to render on the row or card, which is an ancestor of it. The
|
|
8
|
+
* menu sits in a leaf `<td>` (table) / footer `Flex` (grid), so an overlay
|
|
9
|
+
* mounted there would cover the button and nothing else. Rather than hoist the
|
|
10
|
+
* mutation up into both `AssetRow` and `AssetCard` (duplicating it, and moving
|
|
11
|
+
* it away from the control that owns it), the busy flag travels up through
|
|
12
|
+
* context and the ancestor renders the overlay.
|
|
13
|
+
*
|
|
14
|
+
* Scoped per asset id rather than a single boolean: a replace on one row must
|
|
15
|
+
* not blank out every other row. Modelled on `isMovePending` in
|
|
16
|
+
* `AssetsDndProvider`, which does the same thing for drag-moves — that one is
|
|
17
|
+
* list-wide because a move genuinely blocks the whole list.
|
|
18
|
+
*/
|
|
19
|
+
export interface BusyAssets {
|
|
20
|
+
/** Whether this asset has a mutation in flight. */
|
|
21
|
+
isBusy: (id: number) => boolean;
|
|
22
|
+
/** The message to show while it is, or `null`. */
|
|
23
|
+
getBusyMessage: (id: number) => string | null;
|
|
24
|
+
/**
|
|
25
|
+
* Marks the asset busy and returns the release function. Pair it with
|
|
26
|
+
* `try`/`finally` so the flag clears on failure too.
|
|
27
|
+
*/
|
|
28
|
+
markBusy: (id: number, message: string) => () => void;
|
|
29
|
+
}
|
|
30
|
+
export declare const BusyAssetsProvider: ({ children }: {
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
}) => import("react").FunctionComponentElement<import("react").ProviderProps<BusyAssets | null>>;
|
|
33
|
+
/**
|
|
34
|
+
* Optional by design: `AssetActionsMenu`, `AssetRow` and `AssetCard` are also
|
|
35
|
+
* rendered in tests and in the asset picker, outside this provider. Without it
|
|
36
|
+
* the mutation still runs, it just shows no row-level feedback.
|
|
37
|
+
*/
|
|
38
|
+
export declare const useBusyAssetsOptional: () => BusyAssets | null;
|
|
@@ -6,16 +6,30 @@ interface UseInfiniteAssetsOptions {
|
|
|
6
6
|
search?: string;
|
|
7
7
|
/** Extra `filters[$and]` entries for the files query. */
|
|
8
8
|
filters?: Record<string, unknown>[];
|
|
9
|
-
/**
|
|
10
|
-
* Stable fingerprint of `filters` — a change resets the accumulated pages
|
|
11
|
-
* (the array identity itself changes every render).
|
|
12
|
-
*/
|
|
13
|
-
filtersKey?: string;
|
|
14
9
|
/** Structural switch: an `is [folder]`-only type badge means no file can match. */
|
|
15
10
|
enabled?: boolean;
|
|
16
11
|
}
|
|
17
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Infinite scroll over `/upload/files`, keeping one accumulated slot per page.
|
|
14
|
+
*
|
|
15
|
+
* The caller MUST render the returned `subscribers` node — that is what keeps
|
|
16
|
+
* every loaded page subscribed, so `{Asset, LIST}` invalidations keep the whole
|
|
17
|
+
* list consistent rather than only the current page.
|
|
18
|
+
*/
|
|
19
|
+
declare const useInfiniteAssets: ({ folder, sort, search, filters, enabled, }?: UseInfiniteAssetsOptions) => {
|
|
18
20
|
assets: File[];
|
|
21
|
+
subscribers: null;
|
|
22
|
+
pagination: undefined;
|
|
23
|
+
isLoading: boolean;
|
|
24
|
+
isFetchingMore: boolean;
|
|
25
|
+
hasNextPage: boolean;
|
|
26
|
+
fetchNextPage: () => void;
|
|
27
|
+
error: undefined;
|
|
28
|
+
} | {
|
|
29
|
+
assets: File[];
|
|
30
|
+
subscribers: import("react").FunctionComponentElement<{
|
|
31
|
+
children?: import("react").ReactNode | undefined;
|
|
32
|
+
}>;
|
|
19
33
|
pagination: Pagination | undefined;
|
|
20
34
|
isLoading: boolean;
|
|
21
35
|
isFetchingMore: boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
interface UseInfiniteScrollSentinelArgs {
|
|
2
|
+
/** Whether there is a further page to request. */
|
|
3
|
+
hasNextPage: boolean;
|
|
4
|
+
/** Whether a subsequent page is already in flight. */
|
|
5
|
+
isFetchingMore: boolean;
|
|
6
|
+
/** Called to request the next page. Held in a ref, so it need not be stable. */
|
|
7
|
+
onLoadMore: () => void;
|
|
8
|
+
/**
|
|
9
|
+
* Passed to the `IntersectionObserver`. Read once, when the sentinel node
|
|
10
|
+
* attaches — changing it afterwards does NOT rebuild the observer, so a
|
|
11
|
+
* later `threshold`/`rootMargin` is silently ignored. Pass a stable, ideally
|
|
12
|
+
* module-level, object.
|
|
13
|
+
*/
|
|
14
|
+
options?: IntersectionObserverInit;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Infinite-scroll trigger for the media library list.
|
|
18
|
+
*
|
|
19
|
+
* Returns a callback ref to place on a sentinel element rendered after the last
|
|
20
|
+
* row. Three deliberate choices:
|
|
21
|
+
*
|
|
22
|
+
* 1. **Loading is driven only by fresh observer readings.** A fetch fires from
|
|
23
|
+
* the `IntersectionObserver` callback — never from a state/prop change — so
|
|
24
|
+
* it can't react to a stale `isIntersecting` from before newly loaded rows
|
|
25
|
+
* rendered (which fetched an extra page on every trigger).
|
|
26
|
+
*
|
|
27
|
+
* 2. **Each settled page re-observes the sentinel.** An `IntersectionObserver`
|
|
28
|
+
* only fires on a *transition*. When the sentinel stays on screen (a page
|
|
29
|
+
* that doesn't fill the viewport — tall viewport, short page, grid fitting
|
|
30
|
+
* the whole page) it would never fire again and loading would stall. So when
|
|
31
|
+
* `isFetchingMore` settles back to false we re-observe, forcing a fresh
|
|
32
|
+
* reading against the new layout: still on screen → load the next page;
|
|
33
|
+
* viewport now filled → stop.
|
|
34
|
+
*
|
|
35
|
+
* 3. **A callback ref, not a stable object ref.** The sentinel only mounts once
|
|
36
|
+
* the first page has rendered (the list shows a loader before that). A
|
|
37
|
+
* callback ref (re)binds the observer exactly when the node mounts/unmounts,
|
|
38
|
+
* so the observer can't miss a sentinel that appears after the hook first ran.
|
|
39
|
+
*/
|
|
40
|
+
export declare const useInfiniteScrollSentinel: ({ hasNextPage, isFetchingMore, onLoadMore, options, }: UseInfiniteScrollSentinelArgs) => (node: HTMLElement | null) => void;
|
|
41
|
+
export {};
|
|
@@ -25,6 +25,16 @@ export declare const createEmptySelection: () => SelectionState;
|
|
|
25
25
|
* The toggled key becomes the new anchor.
|
|
26
26
|
*/
|
|
27
27
|
export declare const toggleSelection: (state: SelectionState, key: ItemKey) => SelectionState;
|
|
28
|
+
/**
|
|
29
|
+
* Subtractive counterpart to {@link toggleSelection} — removes a key without the
|
|
30
|
+
* add-if-absent ambiguity, leaving the rest of the selection alone. Used when a
|
|
31
|
+
* single-item affordance (a row's "..." menu) makes exactly one key stale.
|
|
32
|
+
*
|
|
33
|
+
* Idempotent: removing a key that was never selected is a no-op. The anchor is
|
|
34
|
+
* dropped only when it is the removed key, so a Shift+click range built around
|
|
35
|
+
* other rows survives.
|
|
36
|
+
*/
|
|
37
|
+
export declare const deselect: (state: SelectionState, key: ItemKey) => SelectionState;
|
|
28
38
|
/**
|
|
29
39
|
* Shift+click — selects the contiguous range between the current anchor and the
|
|
30
40
|
* target in render order, replacing the current selection. The anchor stays put.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dispatch } from '@reduxjs/toolkit';
|
|
2
|
-
import type { CreateFilesStream, File as UploadedFile,
|
|
2
|
+
import type { CreateFilesStream, File as UploadedFile, GenerateAIMetadata, UploadFileInfo } from '../../../../shared/contracts/files';
|
|
3
3
|
interface UploadFilesArgs {
|
|
4
4
|
formData: FormData;
|
|
5
5
|
totalFiles: number;
|
|
@@ -54,10 +54,9 @@ export declare const maybeGenerateMetadata: ({ file, index, uploadId, enabled, d
|
|
|
54
54
|
}) => void;
|
|
55
55
|
declare const uploadApi: import("@reduxjs/toolkit/query").Api<import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, import("@reduxjs/toolkit/dist/query/endpointDefinitions").UpdateDefinitions<{}, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", never> & {
|
|
56
56
|
/**
|
|
57
|
-
* Upload files to `/upload/
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* `XHR.upload.onprogress`.
|
|
57
|
+
* Upload files to `/upload/files`, one request per file, through a worker
|
|
58
|
+
* pool of `concurrency` parallel requests (default 1 = sequential). Real
|
|
59
|
+
* per-file byte progress comes from `XHR.upload.onprogress`.
|
|
61
60
|
*/
|
|
62
61
|
uploadFiles: import("@reduxjs/toolkit/query").MutationDefinition<UploadFilesArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">;
|
|
63
62
|
/**
|
|
@@ -92,9 +91,9 @@ declare const uploadApi: import("@reduxjs/toolkit/query").Api<import("@reduxjs/t
|
|
|
92
91
|
*/
|
|
93
92
|
generateAiMetadata: import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
94
93
|
fileIds: number[];
|
|
95
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder",
|
|
94
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", GenerateAIMetadata.FileResult[], "adminApi">;
|
|
96
95
|
}, "adminApi", "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", typeof import("@reduxjs/toolkit/query").coreModuleName | typeof import("@reduxjs/toolkit/dist/query/react").reactHooksModuleName>;
|
|
97
96
|
export declare const useUploadFilesMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadFilesArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">>, useUploadFileSilentlyMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadEntry, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile, "adminApi">>, useRetryCancelledFilesMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">>, useUploadFromUrlsMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadFromUrlsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", CreateFilesStream.Response, "adminApi">>, useGenerateAiMetadataMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
98
97
|
fileIds: number[];
|
|
99
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder",
|
|
98
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", GenerateAIMetadata.FileResult[], "adminApi">>;
|
|
100
99
|
export { uploadApi };
|
|
@@ -21,7 +21,12 @@ interface BulkMoveParams {
|
|
|
21
21
|
/** `null` moves the items to the root of the Media Library. */
|
|
22
22
|
destinationFolderId: number | null;
|
|
23
23
|
}
|
|
24
|
-
export declare const useCreateFolderMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Pick<Folder, "name" | "parent">, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", Folder, "adminApi">>,
|
|
24
|
+
export declare const useCreateFolderMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Pick<Folder, "name" | "parent">, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", Folder, "adminApi">>, useUpdateFolderMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
25
|
+
id: number;
|
|
26
|
+
} & {
|
|
27
|
+
name: string;
|
|
28
|
+
parent: number | null;
|
|
29
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", Folder, "adminApi">>, useGetFoldersQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void | GetFoldersParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", Folder[], "adminApi">>, useGetFolderQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
25
30
|
id: number;
|
|
26
31
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", FolderWithCounts, "adminApi">>, useGetAllFoldersQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", Folder[], "adminApi">>, useGetFolderStructureQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", FolderNode[], "adminApi">>, useBulkMoveMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<BulkMoveParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", {
|
|
27
32
|
data: {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { type ItemLocations } from './itemLocations';
|
|
1
2
|
import type { DragItemData } from '../types/dnd';
|
|
2
3
|
/**
|
|
3
4
|
* Reconstruct the drag set from a bulk-actions selection so the dialog can feed
|
|
4
5
|
* the exact same `DragItemData[]` into `computeValidDropTargets` / the canonical
|
|
5
6
|
* `canDropItemOnFolder` predicate that pointer drag uses.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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.
|
|
9
10
|
* Names are irrelevant to drop validation, so they are left empty.
|
|
10
11
|
*/
|
|
11
|
-
export declare const buildDragSetFromSelection: (selectedIds: ReadonlySet<number>, selectedFolderIds: ReadonlySet<number>,
|
|
12
|
+
export declare const buildDragSetFromSelection: (selectedIds: ReadonlySet<number>, selectedFolderIds: ReadonlySet<number>, locations: ItemLocations, fallbackFolderId: number | null) => DragItemData[];
|
|
@@ -2,7 +2,13 @@ import type { IntlShape } from 'react-intl';
|
|
|
2
2
|
interface FormatMoveSuccessArgs {
|
|
3
3
|
formatMessage: IntlShape['formatMessage'];
|
|
4
4
|
count: number;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Leaf name of the folder the items came from, or `null` when the move spans
|
|
7
|
+
* several source folders and no single one can be named — a global-search
|
|
8
|
+
* selection can hold items from anywhere. The wording then omits the source
|
|
9
|
+
* rather than naming one folder and implying the rest came from it too.
|
|
10
|
+
*/
|
|
11
|
+
source: string | null;
|
|
6
12
|
destination: string;
|
|
7
13
|
}
|
|
8
14
|
/**
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
*/
|
|
9
|
+
export declare const getRelationId: (relation: number | string | {
|
|
10
|
+
id?: number;
|
|
11
|
+
} | null | undefined) => number | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SyntheticEvent } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* True when the event really originated inside `currentTarget`'s DOM subtree.
|
|
4
|
+
*
|
|
5
|
+
* Portaled content (Radix menus, modals, select popovers) bubbles through the
|
|
6
|
+
* React tree, so a row's handlers see events coming from dialogs rendered by
|
|
7
|
+
* its own children. Guarding on DOM containment keeps those out — without
|
|
8
|
+
* calling `stopPropagation`, which would also kill the native event before it
|
|
9
|
+
* reaches `document`, where Radix listens in order to dismiss its layers.
|
|
10
|
+
*/
|
|
11
|
+
export declare const isEventFromWithin: (event: SyntheticEvent) => boolean;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { File } from '../../../../shared/contracts/files';
|
|
2
|
+
import type { Folder } from '../../../../shared/contracts/folders';
|
|
3
|
+
/**
|
|
4
|
+
* Where each loaded item actually lives, keyed by id.
|
|
5
|
+
*
|
|
6
|
+
* Search results are global, so the folder currently open (`?folder=`) says
|
|
7
|
+
* nothing about a selected item's location. The loaded lists do: the server
|
|
8
|
+
* populates `folder` on `/upload/files` and `parent` on `/upload/folders`.
|
|
9
|
+
*
|
|
10
|
+
* `undefined` means "not in the loaded list" and is distinct from `null`
|
|
11
|
+
* ("lives at the root") — the two lead to different move validation.
|
|
12
|
+
*/
|
|
13
|
+
export interface ItemLocations {
|
|
14
|
+
fileFolderId: (id: number) => number | null | undefined;
|
|
15
|
+
folderParentId: (id: number) => number | null | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** Every id misses — used where no list is loaded (e.g. an isolated provider). */
|
|
18
|
+
export declare const emptyItemLocations: ItemLocations;
|
|
19
|
+
/**
|
|
20
|
+
* Build the lookup once per list. Callers memoize on the rows so the identity
|
|
21
|
+
* stays stable: `BulkMoveDialog` memoizes its destination walk on the items
|
|
22
|
+
* derived from it.
|
|
23
|
+
*/
|
|
24
|
+
export declare const buildItemLocations: (assets: File[], folders: Folder[]) => ItemLocations;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve an item's location, falling back to the folder currently open when it
|
|
27
|
+
* is not in the loaded list. The fallback is unreachable in practice — selection
|
|
28
|
+
* clears whenever the list identity changes and infinite scroll only appends —
|
|
29
|
+
* but a stale parent beats silently dropping the item from the move.
|
|
30
|
+
*/
|
|
31
|
+
export declare const locateItem: (locations: ItemLocations, kind: "file" | "folder", id: number, fallbackFolderId: number | null) => number | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DragItemData } from '../types/dnd';
|
|
2
|
+
/**
|
|
3
|
+
* Where an item currently lives, regardless of its kind — folders carry their
|
|
4
|
+
* location on `parentId`, files on `folderId`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const sourceFolderIdOf: (item: DragItemData) => number | null;
|
|
7
|
+
/**
|
|
8
|
+
* The one folder every item in a move came from, or `null` when there isn't one.
|
|
9
|
+
*
|
|
10
|
+
* A selection made under a global search can hold items from anywhere, so a move
|
|
11
|
+
* has a nameable source only when the whole set agrees on it. `null` also covers
|
|
12
|
+
* the empty set. Callers pass the result straight to `formatMoveSuccessMessage`,
|
|
13
|
+
* which drops the source from the wording rather than crediting one item's
|
|
14
|
+
* folder to all of them.
|
|
15
|
+
*
|
|
16
|
+
* Note `null` is overloaded on purpose at the *label* level: an item at the
|
|
17
|
+
* Media Library root also has a `null` location, and both cases end up reading
|
|
18
|
+
* as "no folder to name". Use `hasUniformSource` when the difference matters.
|
|
19
|
+
*/
|
|
20
|
+
export declare const uniformSourceFolderId: (items: DragItemData[]) => number | null;
|
|
21
|
+
/** Whether every item in the set came from the same folder. False for an empty set. */
|
|
22
|
+
export declare const hasUniformSource: (items: DragItemData[]) => boolean;
|
|
@@ -100,6 +100,9 @@ var en = {
|
|
|
100
100
|
"upload.progress.maximize": "Maximize",
|
|
101
101
|
"upload.progress.minimize": "Minimize",
|
|
102
102
|
"upload.progress.close": "Close",
|
|
103
|
+
"beta.badge": "Beta",
|
|
104
|
+
"beta.notice.close": "Close",
|
|
105
|
+
"beta.notice.content": "This is a beta version of the Media Library. Some features are still in progress — please report any issue you run into.",
|
|
103
106
|
"bulk.select.label": "Select all assets",
|
|
104
107
|
"button.next": "Next",
|
|
105
108
|
"new": "New",
|
|
@@ -116,6 +119,7 @@ var en = {
|
|
|
116
119
|
"control-card.save-focal-point": "Save focal point",
|
|
117
120
|
"control-card.download": "Download",
|
|
118
121
|
"control-card.edit": "Edit",
|
|
122
|
+
"control-card.more-actions": "More actions",
|
|
119
123
|
"control-card.remove-selection": "Remove from selection",
|
|
120
124
|
"control-card.replace-media": "Replace Media",
|
|
121
125
|
"control-card.save": "Save",
|
|
@@ -133,11 +137,16 @@ var en = {
|
|
|
133
137
|
"header.actions.add-assets": "Add new assets",
|
|
134
138
|
"header.actions.add-folder": "Add new folder",
|
|
135
139
|
"folder.create.title": "New folder",
|
|
140
|
+
"folder.create.title-in": "New folder in {folderName}",
|
|
136
141
|
"folder.form.name.label": "Folder name",
|
|
137
142
|
"folder.create.submit": "Create folder",
|
|
138
143
|
"folder.create.form.error.name-required": "Name is required",
|
|
139
144
|
"folder.create.form.error.unknown": "An error occurred while creating the folder",
|
|
140
145
|
"folder.create.success": "Folder has been created",
|
|
146
|
+
"folder.rename.title": "Rename folder",
|
|
147
|
+
"folder.rename.submit": "Save",
|
|
148
|
+
"folder.rename.form.error.unknown": "An error occurred while renaming the folder",
|
|
149
|
+
"folder.rename.success": "Folder has been renamed",
|
|
141
150
|
"header.actions.add-assets.folder": "folder",
|
|
142
151
|
"header.actions.upload-assets": "Upload assets",
|
|
143
152
|
"header.actions.upload-new-asset": "Upload new asset",
|
|
@@ -223,8 +232,19 @@ var en = {
|
|
|
223
232
|
"list.assets.preview-asset": "Preview for the video at path {path}",
|
|
224
233
|
"list.assets.selected": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 asset} other {# assets}}",
|
|
225
234
|
"list-assets-select": "Select {name} asset",
|
|
235
|
+
"list.assets.actions.replace": "Replace media",
|
|
236
|
+
"list.assets.actions.copy-link": "Copy link to media",
|
|
237
|
+
"list.assets.actions.download": "Download media",
|
|
238
|
+
"list.assets.actions.move": "Move to folder",
|
|
239
|
+
"list.assets.actions.delete": "Delete",
|
|
226
240
|
"list.assets.type-not-allowed": "This type of file is not allowed.",
|
|
227
241
|
"list.assets.to-upload": "{number, plural, =0 {No asset} one {1 asset} other {# assets}} ready to upload",
|
|
242
|
+
"list.folder.actions.copy-link": "Copy link to folder",
|
|
243
|
+
"list.folder.actions.copy-link.success": "Folder link copied.",
|
|
244
|
+
"list.folder.actions.copy-link.error": "Failed to copy the folder link.",
|
|
245
|
+
"list.folder.actions.rename": "Rename folder",
|
|
246
|
+
"list.folder.actions.move": "Move to folder",
|
|
247
|
+
"list.folder.actions.delete": "Delete folder",
|
|
228
248
|
"list.folder.edit": "Edit folder",
|
|
229
249
|
"list.folder.select": "Select {name} folder",
|
|
230
250
|
"list.folder.subtitle": "{folderCount, plural, one {# folder} other {# folders}}, {filesCount, plural, one {# asset} other {# assets}}",
|
|
@@ -317,6 +337,7 @@ var en = {
|
|
|
317
337
|
"list.table.header.sort": "Sort on {label}",
|
|
318
338
|
"list.table.header.select-all": "Select all",
|
|
319
339
|
"list.table.row.select": "Select {name}",
|
|
340
|
+
"list.table.row.metadata-missing": "This asset is missing metadata (caption or alternative text).",
|
|
320
341
|
"list.table.content.empty-label": "This field is empty",
|
|
321
342
|
"list.bulk-actions.label": "Bulk actions",
|
|
322
343
|
"list.bulk-actions.selected-count": "{count, plural, =1 {# item selected} other {# items selected}}",
|
|
@@ -330,8 +351,11 @@ var en = {
|
|
|
330
351
|
"list.bulk-actions.move": "Move",
|
|
331
352
|
"list.bulk-actions.move.title": "Move elements to",
|
|
332
353
|
"list.bulk-actions.move.location": "Location",
|
|
354
|
+
"list.bulk-actions.move.no-destination": "There is no other folder to move this to.",
|
|
355
|
+
"list.bulk-actions.move.load-error": "Couldn't load the folder list. Please try again.",
|
|
333
356
|
"list.bulk-actions.move.submit": "Move",
|
|
334
357
|
"list.bulk-actions.move.success": "{count, plural, =1 {# element has} other {# elements have}} been moved from {source} to {destination}",
|
|
358
|
+
"list.bulk-actions.move.success-multiple-sources": "{count, plural, =1 {# element has} other {# elements have}} been moved to {destination}",
|
|
335
359
|
"list.bulk-actions.move.error": "An error occurred while moving the items.",
|
|
336
360
|
"list.bulk-actions.delete": "Delete",
|
|
337
361
|
"list.bulk-actions.delete.confirm.title": "Delete {count, plural, =1 {# item} other {# items}}?",
|
|
@@ -364,11 +388,8 @@ var en = {
|
|
|
364
388
|
"sidebar.tree.expand": "Expand {name}",
|
|
365
389
|
"sidebar.tree.collapse": "Collapse {name}",
|
|
366
390
|
"sidebar.tree.empty": "No folders yet",
|
|
367
|
-
"sidebar.tree.no-results": "No folders match \"{query}\"",
|
|
368
391
|
"sidebar.tree.loading": "Loading folders...",
|
|
369
|
-
"sidebar.tree.error": "Could not load folders."
|
|
370
|
-
"sidebar.search.label": "Search folders",
|
|
371
|
-
"sidebar.search.placeholder": "Search folders"
|
|
392
|
+
"sidebar.tree.error": "Could not load folders."
|
|
372
393
|
};
|
|
373
394
|
|
|
374
395
|
module.exports = en;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -98,6 +98,9 @@ var en = {
|
|
|
98
98
|
"upload.progress.maximize": "Maximize",
|
|
99
99
|
"upload.progress.minimize": "Minimize",
|
|
100
100
|
"upload.progress.close": "Close",
|
|
101
|
+
"beta.badge": "Beta",
|
|
102
|
+
"beta.notice.close": "Close",
|
|
103
|
+
"beta.notice.content": "This is a beta version of the Media Library. Some features are still in progress — please report any issue you run into.",
|
|
101
104
|
"bulk.select.label": "Select all assets",
|
|
102
105
|
"button.next": "Next",
|
|
103
106
|
"new": "New",
|
|
@@ -114,6 +117,7 @@ var en = {
|
|
|
114
117
|
"control-card.save-focal-point": "Save focal point",
|
|
115
118
|
"control-card.download": "Download",
|
|
116
119
|
"control-card.edit": "Edit",
|
|
120
|
+
"control-card.more-actions": "More actions",
|
|
117
121
|
"control-card.remove-selection": "Remove from selection",
|
|
118
122
|
"control-card.replace-media": "Replace Media",
|
|
119
123
|
"control-card.save": "Save",
|
|
@@ -131,11 +135,16 @@ var en = {
|
|
|
131
135
|
"header.actions.add-assets": "Add new assets",
|
|
132
136
|
"header.actions.add-folder": "Add new folder",
|
|
133
137
|
"folder.create.title": "New folder",
|
|
138
|
+
"folder.create.title-in": "New folder in {folderName}",
|
|
134
139
|
"folder.form.name.label": "Folder name",
|
|
135
140
|
"folder.create.submit": "Create folder",
|
|
136
141
|
"folder.create.form.error.name-required": "Name is required",
|
|
137
142
|
"folder.create.form.error.unknown": "An error occurred while creating the folder",
|
|
138
143
|
"folder.create.success": "Folder has been created",
|
|
144
|
+
"folder.rename.title": "Rename folder",
|
|
145
|
+
"folder.rename.submit": "Save",
|
|
146
|
+
"folder.rename.form.error.unknown": "An error occurred while renaming the folder",
|
|
147
|
+
"folder.rename.success": "Folder has been renamed",
|
|
139
148
|
"header.actions.add-assets.folder": "folder",
|
|
140
149
|
"header.actions.upload-assets": "Upload assets",
|
|
141
150
|
"header.actions.upload-new-asset": "Upload new asset",
|
|
@@ -221,8 +230,19 @@ var en = {
|
|
|
221
230
|
"list.assets.preview-asset": "Preview for the video at path {path}",
|
|
222
231
|
"list.assets.selected": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 asset} other {# assets}}",
|
|
223
232
|
"list-assets-select": "Select {name} asset",
|
|
233
|
+
"list.assets.actions.replace": "Replace media",
|
|
234
|
+
"list.assets.actions.copy-link": "Copy link to media",
|
|
235
|
+
"list.assets.actions.download": "Download media",
|
|
236
|
+
"list.assets.actions.move": "Move to folder",
|
|
237
|
+
"list.assets.actions.delete": "Delete",
|
|
224
238
|
"list.assets.type-not-allowed": "This type of file is not allowed.",
|
|
225
239
|
"list.assets.to-upload": "{number, plural, =0 {No asset} one {1 asset} other {# assets}} ready to upload",
|
|
240
|
+
"list.folder.actions.copy-link": "Copy link to folder",
|
|
241
|
+
"list.folder.actions.copy-link.success": "Folder link copied.",
|
|
242
|
+
"list.folder.actions.copy-link.error": "Failed to copy the folder link.",
|
|
243
|
+
"list.folder.actions.rename": "Rename folder",
|
|
244
|
+
"list.folder.actions.move": "Move to folder",
|
|
245
|
+
"list.folder.actions.delete": "Delete folder",
|
|
226
246
|
"list.folder.edit": "Edit folder",
|
|
227
247
|
"list.folder.select": "Select {name} folder",
|
|
228
248
|
"list.folder.subtitle": "{folderCount, plural, one {# folder} other {# folders}}, {filesCount, plural, one {# asset} other {# assets}}",
|
|
@@ -315,6 +335,7 @@ var en = {
|
|
|
315
335
|
"list.table.header.sort": "Sort on {label}",
|
|
316
336
|
"list.table.header.select-all": "Select all",
|
|
317
337
|
"list.table.row.select": "Select {name}",
|
|
338
|
+
"list.table.row.metadata-missing": "This asset is missing metadata (caption or alternative text).",
|
|
318
339
|
"list.table.content.empty-label": "This field is empty",
|
|
319
340
|
"list.bulk-actions.label": "Bulk actions",
|
|
320
341
|
"list.bulk-actions.selected-count": "{count, plural, =1 {# item selected} other {# items selected}}",
|
|
@@ -328,8 +349,11 @@ var en = {
|
|
|
328
349
|
"list.bulk-actions.move": "Move",
|
|
329
350
|
"list.bulk-actions.move.title": "Move elements to",
|
|
330
351
|
"list.bulk-actions.move.location": "Location",
|
|
352
|
+
"list.bulk-actions.move.no-destination": "There is no other folder to move this to.",
|
|
353
|
+
"list.bulk-actions.move.load-error": "Couldn't load the folder list. Please try again.",
|
|
331
354
|
"list.bulk-actions.move.submit": "Move",
|
|
332
355
|
"list.bulk-actions.move.success": "{count, plural, =1 {# element has} other {# elements have}} been moved from {source} to {destination}",
|
|
356
|
+
"list.bulk-actions.move.success-multiple-sources": "{count, plural, =1 {# element has} other {# elements have}} been moved to {destination}",
|
|
333
357
|
"list.bulk-actions.move.error": "An error occurred while moving the items.",
|
|
334
358
|
"list.bulk-actions.delete": "Delete",
|
|
335
359
|
"list.bulk-actions.delete.confirm.title": "Delete {count, plural, =1 {# item} other {# items}}?",
|
|
@@ -362,11 +386,8 @@ var en = {
|
|
|
362
386
|
"sidebar.tree.expand": "Expand {name}",
|
|
363
387
|
"sidebar.tree.collapse": "Collapse {name}",
|
|
364
388
|
"sidebar.tree.empty": "No folders yet",
|
|
365
|
-
"sidebar.tree.no-results": "No folders match \"{query}\"",
|
|
366
389
|
"sidebar.tree.loading": "Loading folders...",
|
|
367
|
-
"sidebar.tree.error": "Could not load folders."
|
|
368
|
-
"sidebar.search.label": "Search folders",
|
|
369
|
-
"sidebar.search.placeholder": "Search folders"
|
|
390
|
+
"sidebar.tree.error": "Could not load folders."
|
|
370
391
|
};
|
|
371
392
|
|
|
372
393
|
export { en as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"en.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -56,7 +56,12 @@ var adminFile = {
|
|
|
56
56
|
]);
|
|
57
57
|
ctx.body = body;
|
|
58
58
|
},
|
|
59
|
-
|
|
59
|
+
/**
|
|
60
|
+
* `GET /upload/ai-metadata-jobs/pending-count`
|
|
61
|
+
*
|
|
62
|
+
* How many images a backfill job would have to process, i.e. those still
|
|
63
|
+
* missing AI metadata, alongside the total image count.
|
|
64
|
+
*/ async getAIMetadataPendingCount (ctx) {
|
|
60
65
|
const { userAbility } = ctx.state;
|
|
61
66
|
const pm = strapi.service('admin::permission').createPermissionsManager({
|
|
62
67
|
ability: userAbility,
|
|
@@ -86,7 +91,14 @@ var adminFile = {
|
|
|
86
91
|
ctx.badRequest(message);
|
|
87
92
|
}
|
|
88
93
|
},
|
|
89
|
-
|
|
94
|
+
/**
|
|
95
|
+
* `POST /upload/ai-metadata-jobs`
|
|
96
|
+
*
|
|
97
|
+
* Create a backfill job that generates AI metadata for every image still
|
|
98
|
+
* missing it, and return the job so the client can poll it. Processing runs
|
|
99
|
+
* detached from this request; see `generateAIMetadata` for the synchronous
|
|
100
|
+
* counterpart that works on an explicit selection.
|
|
101
|
+
*/ async createAIMetadataJob (ctx) {
|
|
90
102
|
const { userAbility } = ctx.state;
|
|
91
103
|
const pm = strapi.service('admin::permission').createPermissionsManager({
|
|
92
104
|
ability: userAbility,
|
|
@@ -135,14 +147,15 @@ var adminFile = {
|
|
|
135
147
|
}
|
|
136
148
|
},
|
|
137
149
|
/**
|
|
138
|
-
*
|
|
150
|
+
* `POST /upload/actions/generate-ai-metadata`
|
|
139
151
|
*
|
|
140
|
-
*
|
|
141
|
-
* every file has been processed and
|
|
142
|
-
* bad id or a non-image in the
|
|
152
|
+
* Generate AI metadata for the explicit selection of files in the body,
|
|
153
|
+
* synchronously: the request resolves once every file has been processed and
|
|
154
|
+
* reports the outcome per file, so a single bad id or a non-image in the
|
|
155
|
+
* selection never fails the whole batch.
|
|
143
156
|
*
|
|
144
|
-
*
|
|
145
|
-
*/ async
|
|
157
|
+
* For the whole-library backfill, see `createAIMetadataJob`.
|
|
158
|
+
*/ async generateAIMetadata (ctx) {
|
|
146
159
|
const { userAbility } = ctx.state;
|
|
147
160
|
const { body } = ctx.request;
|
|
148
161
|
const pm = strapi.service('admin::permission').createPermissionsManager({
|
|
@@ -163,7 +176,12 @@ var adminFile = {
|
|
|
163
176
|
data: results
|
|
164
177
|
};
|
|
165
178
|
},
|
|
166
|
-
|
|
179
|
+
/**
|
|
180
|
+
* `GET /upload/ai-metadata-jobs/latest`
|
|
181
|
+
*
|
|
182
|
+
* The most recent still-active backfill job, so a client that reloads mid-run
|
|
183
|
+
* can pick the progress bar back up. 404s when nothing is running.
|
|
184
|
+
*/ async getLatestAIMetadataJob (ctx) {
|
|
167
185
|
if (await index.getService('aiMetadata').isEnabled() === false) {
|
|
168
186
|
return ctx.notFound();
|
|
169
187
|
}
|