@strapi/upload 5.47.0 → 5.48.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/components/EditAssetDialog/EditAssetContent.js +12 -2
- package/dist/admin/components/EditAssetDialog/EditAssetContent.js.map +1 -1
- package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs +12 -2
- package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs.map +1 -1
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js +1 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js.map +1 -1
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs +1 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs.map +1 -1
- package/dist/admin/future/components/Drawer.js +7 -2
- package/dist/admin/future/components/Drawer.js.map +1 -1
- package/dist/admin/future/components/Drawer.mjs +7 -2
- package/dist/admin/future/components/Drawer.mjs.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.js +33 -29
- package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.mjs +36 -32
- package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.js +2 -2
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +3 -3
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +733 -148
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +737 -155
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js +25 -5
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs +25 -5
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs.map +1 -1
- package/dist/admin/future/services/api.js +124 -200
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +124 -200
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +88 -1
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +86 -2
- package/dist/admin/future/services/assets.mjs.map +1 -1
- package/dist/admin/future/services/folders.js +33 -1
- package/dist/admin/future/services/folders.js.map +1 -1
- package/dist/admin/future/services/folders.mjs +33 -2
- package/dist/admin/future/services/folders.mjs.map +1 -1
- package/dist/admin/future/services/settings.js +18 -0
- package/dist/admin/future/services/settings.js.map +1 -0
- package/dist/admin/future/services/settings.mjs +16 -0
- package/dist/admin/future/services/settings.mjs.map +1 -0
- package/dist/admin/future/services/uploadFileViaXHR.js +92 -0
- package/dist/admin/future/services/uploadFileViaXHR.js.map +1 -0
- package/dist/admin/future/services/uploadFileViaXHR.mjs +88 -0
- package/dist/admin/future/services/uploadFileViaXHR.mjs.map +1 -0
- package/dist/admin/future/store/uploadProgress.js +32 -26
- package/dist/admin/future/store/uploadProgress.js.map +1 -1
- package/dist/admin/future/store/uploadProgress.mjs +32 -27
- package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
- package/dist/admin/future/utils/createRafBatcher.js +42 -0
- package/dist/admin/future/utils/createRafBatcher.js.map +1 -0
- package/dist/admin/future/utils/createRafBatcher.mjs +40 -0
- package/dist/admin/future/utils/createRafBatcher.mjs.map +1 -0
- package/dist/admin/future/utils/downloadFile.js +19 -0
- package/dist/admin/future/utils/downloadFile.js.map +1 -0
- package/dist/admin/future/utils/downloadFile.mjs +17 -0
- package/dist/admin/future/utils/downloadFile.mjs.map +1 -0
- package/dist/admin/hooks/useAssets.js +5 -3
- package/dist/admin/hooks/useAssets.js.map +1 -1
- package/dist/admin/hooks/useAssets.mjs +5 -3
- package/dist/admin/hooks/useAssets.mjs.map +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/EditAssetDialog/EditAssetContent.d.ts +2 -1
- package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +22 -0
- package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetPreview.d.ts +4 -1
- package/dist/admin/src/future/services/api.d.ts +9 -8
- package/dist/admin/src/future/services/assets.d.ts +11 -2
- package/dist/admin/src/future/services/folders.d.ts +1 -1
- package/dist/admin/src/future/services/uploadFileViaXHR.d.ts +34 -0
- package/dist/admin/src/future/store/uploadProgress.d.ts +17 -4
- package/dist/admin/src/future/utils/createRafBatcher.d.ts +23 -0
- package/dist/admin/src/future/utils/downloadFile.d.ts +6 -0
- package/dist/admin/translations/{dk.json.js → da.json.js} +3 -3
- package/dist/admin/translations/{dk.json.js.map → da.json.js.map} +1 -1
- package/dist/admin/translations/{dk.json.mjs → da.json.mjs} +3 -3
- package/dist/admin/translations/{dk.json.mjs.map → da.json.mjs.map} +1 -1
- package/dist/admin/translations/en.json.js +26 -1
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +26 -1
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/bootstrap.js +0 -3
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/bootstrap.mjs +0 -3
- package/dist/server/bootstrap.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +69 -118
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +69 -118
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/routes/admin.js +2 -2
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +2 -2
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/services/ai-metadata-jobs.js +0 -23
- package/dist/server/services/ai-metadata-jobs.js.map +1 -1
- package/dist/server/services/ai-metadata-jobs.mjs +0 -23
- package/dist/server/services/ai-metadata-jobs.mjs.map +1 -1
- package/dist/server/services/image-manipulation.js +16 -8
- package/dist/server/services/image-manipulation.js.map +1 -1
- package/dist/server/services/image-manipulation.mjs +16 -8
- package/dist/server/services/image-manipulation.mjs.map +1 -1
- package/dist/server/services/upload.js +1 -1
- package/dist/server/services/upload.js.map +1 -1
- package/dist/server/services/upload.mjs +1 -1
- package/dist/server/services/upload.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +6 -8
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +1 -1
- package/dist/server/src/index.d.ts +1 -2
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/ai-metadata-jobs.d.ts +0 -1
- package/dist/server/src/services/ai-metadata-jobs.d.ts.map +1 -1
- package/dist/server/src/services/image-manipulation.d.ts +5 -0
- package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +0 -1
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/upload.d.ts.map +1 -1
- package/dist/server/src/types.d.ts +2 -2
- package/dist/server/src/types.d.ts.map +1 -1
- package/dist/shared/contracts/files.d.ts +19 -2
- package/dist/shared/contracts/files.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -10,9 +10,13 @@ var styledComponents = require('styled-components');
|
|
|
10
10
|
var Drawer = require('../../../../components/Drawer.js');
|
|
11
11
|
var enums = require('../../../../enums.js');
|
|
12
12
|
var assets = require('../../../../services/assets.js');
|
|
13
|
+
var folders = require('../../../../services/folders.js');
|
|
14
|
+
var settings = require('../../../../services/settings.js');
|
|
15
|
+
var downloadFile = require('../../../../utils/downloadFile.js');
|
|
13
16
|
var files = require('../../../../utils/files.js');
|
|
14
17
|
var getAssetIcon = require('../../../../utils/getAssetIcon.js');
|
|
15
18
|
var translations = require('../../../../utils/translations.js');
|
|
19
|
+
var useFolderInfo = require('../../hooks/useFolderInfo.js');
|
|
16
20
|
var AssetPreview = require('./AssetPreview.js');
|
|
17
21
|
|
|
18
22
|
function _interopNamespaceDefault(e) {
|
|
@@ -36,6 +40,22 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
36
40
|
|
|
37
41
|
// Name of the parameter to look for in the URL to open the drawer
|
|
38
42
|
const URL_PARAM = 'assetId';
|
|
43
|
+
const DrawerNotifyContext = /*#__PURE__*/ React__namespace.createContext(null);
|
|
44
|
+
const useDrawerNotify = ()=>{
|
|
45
|
+
const ctx = React__namespace.useContext(DrawerNotifyContext);
|
|
46
|
+
if (!ctx) {
|
|
47
|
+
throw new Error('useDrawerNotify must be used within AssetDetails');
|
|
48
|
+
}
|
|
49
|
+
return ctx;
|
|
50
|
+
};
|
|
51
|
+
const AssetOperationsContext = /*#__PURE__*/ React__namespace.createContext(null);
|
|
52
|
+
const useAssetOperation = ()=>{
|
|
53
|
+
const ctx = React__namespace.useContext(AssetOperationsContext);
|
|
54
|
+
if (!ctx) {
|
|
55
|
+
throw new Error('useAssetOperation must be used within AssetDetails');
|
|
56
|
+
}
|
|
57
|
+
return ctx;
|
|
58
|
+
};
|
|
39
59
|
/* -------------------------------------------------------------------------------------------------
|
|
40
60
|
* useAssetDetailsParam - sync drawer visibility with URL ?{URL_PARAM}={id}
|
|
41
61
|
* -----------------------------------------------------------------------------------------------*/ const useAssetDetailsParam = ()=>{
|
|
@@ -43,51 +63,49 @@ const URL_PARAM = 'assetId';
|
|
|
43
63
|
const detailsId = query?.[URL_PARAM];
|
|
44
64
|
const assetId = detailsId ? parseInt(detailsId, 10) : null;
|
|
45
65
|
const hasValidId = assetId !== null && !Number.isNaN(assetId);
|
|
46
|
-
|
|
66
|
+
// Closing is driven by removing the URL param (a navigation), so navigation
|
|
67
|
+
// guards like <Blocker> can intercept it. `isMounted` keeps the drawer in the
|
|
68
|
+
// tree through the slide-out: it stays true once opened and only flips false
|
|
69
|
+
// when the close animation actually ends (see onCloseAnimationEnd), so the
|
|
70
|
+
// close duration lives entirely in CSS — no JS timer.
|
|
71
|
+
const [isMounted, setIsMounted] = React__namespace.useState(hasValidId);
|
|
47
72
|
const displayAssetId = React__namespace.useRef(null);
|
|
48
|
-
const isVisible = hasValidId && !isClosing;
|
|
49
73
|
React__namespace.useEffect(()=>{
|
|
50
74
|
if (hasValidId) {
|
|
51
75
|
displayAssetId.current = assetId;
|
|
76
|
+
setIsMounted(true);
|
|
52
77
|
}
|
|
53
78
|
}, [
|
|
54
79
|
hasValidId,
|
|
55
80
|
assetId
|
|
56
81
|
]);
|
|
82
|
+
const onCloseAnimationEnd = React__namespace.useCallback((event)=>{
|
|
83
|
+
// Ignore animations bubbling up from descendants, and the slide-in.
|
|
84
|
+
if (event.target === event.currentTarget && !hasValidId) {
|
|
85
|
+
setIsMounted(false);
|
|
86
|
+
}
|
|
87
|
+
}, [
|
|
88
|
+
hasValidId
|
|
89
|
+
]);
|
|
57
90
|
const openDetails = React__namespace.useCallback((id)=>{
|
|
58
|
-
setIsClosing(false);
|
|
59
91
|
setQuery({
|
|
60
92
|
[URL_PARAM]: String(id)
|
|
61
|
-
});
|
|
93
|
+
}, 'push', true);
|
|
62
94
|
}, [
|
|
63
95
|
setQuery
|
|
64
96
|
]);
|
|
65
97
|
const closeDetails = React__namespace.useCallback(()=>{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
hasValidId
|
|
70
|
-
]);
|
|
71
|
-
React__namespace.useEffect(()=>{
|
|
72
|
-
if (!isClosing) return;
|
|
73
|
-
const timer = window.setTimeout(()=>{
|
|
74
|
-
setQuery({
|
|
75
|
-
[URL_PARAM]: undefined
|
|
76
|
-
}, 'remove');
|
|
77
|
-
setIsClosing(false);
|
|
78
|
-
displayAssetId.current = null;
|
|
79
|
-
}, Drawer.DRAWER_CLOSE_ANIMATION_MS);
|
|
80
|
-
return ()=>window.clearTimeout(timer);
|
|
98
|
+
setQuery({
|
|
99
|
+
[URL_PARAM]: undefined
|
|
100
|
+
}, 'remove', true);
|
|
81
101
|
}, [
|
|
82
|
-
isClosing,
|
|
83
102
|
setQuery
|
|
84
103
|
]);
|
|
85
|
-
const shouldRenderDrawer = hasValidId || isClosing;
|
|
86
|
-
const drawerAssetId = isClosing ? displayAssetId.current ?? assetId : assetId;
|
|
87
104
|
return {
|
|
88
|
-
assetId:
|
|
89
|
-
isVisible,
|
|
90
|
-
shouldRenderDrawer,
|
|
105
|
+
assetId: hasValidId ? assetId : displayAssetId.current,
|
|
106
|
+
isVisible: hasValidId,
|
|
107
|
+
shouldRenderDrawer: isMounted,
|
|
108
|
+
onCloseAnimationEnd,
|
|
91
109
|
openDetails,
|
|
92
110
|
closeDetails
|
|
93
111
|
};
|
|
@@ -117,7 +135,50 @@ const DetailItem = ({ label, value })=>/*#__PURE__*/ jsxRuntime.jsxs(DetailItemC
|
|
|
117
135
|
});
|
|
118
136
|
/* -------------------------------------------------------------------------------------------------
|
|
119
137
|
* DetailField
|
|
120
|
-
* -----------------------------------------------------------------------------------------------*/
|
|
138
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
139
|
+
* Make the asset details Form behave as a flex column inside Drawer.Body so
|
|
140
|
+
* the scrollable area can grow while the footer stays pinned at the bottom.
|
|
141
|
+
* The Form component from `@strapi/admin/strapi-admin` only forwards `width`
|
|
142
|
+
* + `height` to its Box, so we target the rendered `<form>` element via a
|
|
143
|
+
* styled-components descendant rule.
|
|
144
|
+
*/ const FormShell = styledComponents.styled(designSystem.Box)`
|
|
145
|
+
display: flex;
|
|
146
|
+
flex-direction: column;
|
|
147
|
+
flex: 1;
|
|
148
|
+
min-height: 0;
|
|
149
|
+
|
|
150
|
+
> form {
|
|
151
|
+
display: flex;
|
|
152
|
+
flex-direction: column;
|
|
153
|
+
flex: 1;
|
|
154
|
+
min-height: 0;
|
|
155
|
+
position: relative;
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
/**
|
|
159
|
+
* In-drawer toast container
|
|
160
|
+
*/ const DrawerToastSlot = styledComponents.styled(designSystem.Box)`
|
|
161
|
+
position: absolute;
|
|
162
|
+
top: ${({ theme })=>theme.spaces[2]};
|
|
163
|
+
left: 50%;
|
|
164
|
+
transform: translateX(-50%);
|
|
165
|
+
z-index: 10;
|
|
166
|
+
width: calc(100% - ${({ theme })=>theme.spaces[2]});
|
|
167
|
+
`;
|
|
168
|
+
/**
|
|
169
|
+
* Full-form overlay rendered during long-running drawer-scoped mutations
|
|
170
|
+
* (e.g. replacing the binary). Sits above the toast slot (z-index 10) and
|
|
171
|
+
* the in-drawer Alert so the user can't interact with the form mid-flight.
|
|
172
|
+
*/ const DrawerBusyOverlay = styledComponents.styled(designSystem.Flex)`
|
|
173
|
+
position: absolute;
|
|
174
|
+
inset: 0;
|
|
175
|
+
z-index: 20;
|
|
176
|
+
align-items: center;
|
|
177
|
+
justify-content: center;
|
|
178
|
+
background: ${({ theme })=>theme.colors.neutral0};
|
|
179
|
+
opacity: 0.7;
|
|
180
|
+
`;
|
|
181
|
+
const StyledWarning = styledComponents.styled(icons.WarningCircle)`
|
|
121
182
|
width: 1.6rem;
|
|
122
183
|
height: 1.6rem;
|
|
123
184
|
|
|
@@ -125,7 +186,18 @@ const DetailItem = ({ label, value })=>/*#__PURE__*/ jsxRuntime.jsxs(DetailItemC
|
|
|
125
186
|
fill: ${({ theme })=>theme.colors.warning500};
|
|
126
187
|
}
|
|
127
188
|
`;
|
|
128
|
-
const DetailField = ({ name, label,
|
|
189
|
+
const DetailField = ({ name, label, required })=>{
|
|
190
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
191
|
+
const field = strapiAdmin.useField(name);
|
|
192
|
+
const isSubmitting = strapiAdmin.useForm('DetailField', (state)=>state.isSubmitting);
|
|
193
|
+
const value = field.value ?? '';
|
|
194
|
+
const emptyTooltipLabel = formatMessage({
|
|
195
|
+
id: translations.getTranslationKey('asset-details.field.empty'),
|
|
196
|
+
defaultMessage: '{label} is currently empty.'
|
|
197
|
+
}, {
|
|
198
|
+
label
|
|
199
|
+
});
|
|
200
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
|
|
129
201
|
name: name,
|
|
130
202
|
required: required,
|
|
131
203
|
children: [
|
|
@@ -133,139 +205,651 @@ const DetailField = ({ name, label, value, required })=>/*#__PURE__*/ jsxRuntime
|
|
|
133
205
|
children: label
|
|
134
206
|
}),
|
|
135
207
|
/*#__PURE__*/ jsxRuntime.jsx(designSystem.TextInput, {
|
|
136
|
-
value: value
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
208
|
+
value: value,
|
|
209
|
+
onChange: (event)=>field.onChange(name, event.target.value),
|
|
210
|
+
endAction: !value ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
|
|
211
|
+
label: emptyTooltipLabel,
|
|
212
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(StyledWarning, {
|
|
213
|
+
"aria-label": emptyTooltipLabel,
|
|
214
|
+
role: "img"
|
|
215
|
+
})
|
|
216
|
+
}) : undefined,
|
|
217
|
+
type: "text",
|
|
218
|
+
disabled: isSubmitting
|
|
141
219
|
})
|
|
142
220
|
]
|
|
143
221
|
});
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
paddingTop: 4,
|
|
152
|
-
paddingBottom: 4,
|
|
153
|
-
paddingLeft: 5,
|
|
154
|
-
paddingRight: 5,
|
|
222
|
+
};
|
|
223
|
+
const LocationField = ({ label, rootLabel, folders })=>{
|
|
224
|
+
const field = strapiAdmin.useField('folder');
|
|
225
|
+
const isSubmitting = strapiAdmin.useForm('LocationField', (state)=>state.isSubmitting);
|
|
226
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
|
|
227
|
+
name: "folder",
|
|
228
|
+
required: true,
|
|
155
229
|
children: [
|
|
156
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.
|
|
157
|
-
|
|
158
|
-
fontWeight: "semiBold",
|
|
159
|
-
tag: "h3",
|
|
160
|
-
children: formatMessage({
|
|
161
|
-
id: translations.getTranslationKey('asset-details.fileInfo'),
|
|
162
|
-
defaultMessage: 'File info'
|
|
163
|
-
})
|
|
230
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Label, {
|
|
231
|
+
children: label
|
|
164
232
|
}),
|
|
165
|
-
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
paddingRight: 6,
|
|
173
|
-
alignItems: "flex-start",
|
|
233
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.SingleSelect, {
|
|
234
|
+
value: field.value == null ? '' : String(field.value),
|
|
235
|
+
onChange: (value)=>{
|
|
236
|
+
const next = value === '' ? null : Number(value);
|
|
237
|
+
field.onChange('folder', next);
|
|
238
|
+
},
|
|
239
|
+
disabled: isSubmitting,
|
|
174
240
|
children: [
|
|
175
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
defaultMessage: 'Creation date'
|
|
179
|
-
}),
|
|
180
|
-
value: asset.createdAt ? formatDate(new Date(asset.createdAt), {
|
|
181
|
-
dateStyle: 'long',
|
|
182
|
-
timeStyle: 'short'
|
|
183
|
-
}) : null
|
|
184
|
-
}),
|
|
185
|
-
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
186
|
-
label: formatMessage({
|
|
187
|
-
id: translations.getTranslationKey('asset-details.lastUpdated'),
|
|
188
|
-
defaultMessage: 'Last updated'
|
|
189
|
-
}),
|
|
190
|
-
value: asset.updatedAt ? formatDate(new Date(asset.updatedAt), {
|
|
191
|
-
dateStyle: 'long',
|
|
192
|
-
timeStyle: 'short'
|
|
193
|
-
}) : null
|
|
194
|
-
}),
|
|
195
|
-
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
196
|
-
label: formatMessage({
|
|
197
|
-
id: translations.getTranslationKey('asset-details.createdBy'),
|
|
198
|
-
defaultMessage: 'Created by'
|
|
199
|
-
}),
|
|
200
|
-
value: asset.createdBy ? strapiAdmin.getDisplayName({
|
|
201
|
-
firstname: asset.createdBy.firstname ?? undefined,
|
|
202
|
-
lastname: asset.createdBy.lastname ?? undefined,
|
|
203
|
-
username: asset.createdBy.username ?? undefined,
|
|
204
|
-
email: asset.createdBy.email ?? undefined
|
|
205
|
-
}) ?? '-' : null
|
|
241
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.SingleSelectOption, {
|
|
242
|
+
value: "",
|
|
243
|
+
children: rootLabel
|
|
206
244
|
}),
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
245
|
+
folders.map((folder)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.SingleSelectOption, {
|
|
246
|
+
value: String(folder.id),
|
|
247
|
+
children: folder.name
|
|
248
|
+
}, folder.id))
|
|
249
|
+
]
|
|
250
|
+
})
|
|
251
|
+
]
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
/* -------------------------------------------------------------------------------------------------
|
|
255
|
+
* DeleteAssetButton
|
|
256
|
+
* -----------------------------------------------------------------------------------------------*/ const DeleteAssetButton = ()=>{
|
|
257
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
258
|
+
const { deleteAsset, isDeleting } = useAssetOperation();
|
|
259
|
+
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
|
260
|
+
const handleConfirm = async ()=>{
|
|
261
|
+
await deleteAsset();
|
|
262
|
+
setIsOpen(false);
|
|
263
|
+
};
|
|
264
|
+
const triggerLabel = formatMessage({
|
|
265
|
+
id: translations.getTranslationKey('asset-details.delete.trigger'),
|
|
266
|
+
defaultMessage: 'Delete this file'
|
|
267
|
+
});
|
|
268
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Root, {
|
|
269
|
+
open: isOpen,
|
|
270
|
+
onOpenChange: setIsOpen,
|
|
271
|
+
children: [
|
|
272
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Trigger, {
|
|
273
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
|
274
|
+
withTooltip: false,
|
|
275
|
+
label: triggerLabel,
|
|
276
|
+
variant: "danger-light",
|
|
277
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Trash, {})
|
|
278
|
+
})
|
|
279
|
+
}),
|
|
280
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Content, {
|
|
281
|
+
children: [
|
|
282
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Header, {
|
|
283
|
+
children: formatMessage({
|
|
284
|
+
id: translations.getTranslationKey('asset-details.delete.title'),
|
|
285
|
+
defaultMessage: 'Delete this media file?'
|
|
286
|
+
})
|
|
220
287
|
}),
|
|
221
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
288
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Body, {
|
|
289
|
+
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.WarningCircle, {
|
|
290
|
+
width: "24px",
|
|
291
|
+
height: "24px",
|
|
292
|
+
fill: "danger600"
|
|
225
293
|
}),
|
|
226
|
-
|
|
294
|
+
textAlign: "center",
|
|
295
|
+
children: formatMessage({
|
|
296
|
+
id: translations.getTranslationKey('asset-details.delete.description'),
|
|
297
|
+
defaultMessage: 'This file cannot be recovered once deleted. If it is currently in use, linked content will break and image containers will be empty.'
|
|
298
|
+
})
|
|
227
299
|
}),
|
|
228
|
-
/*#__PURE__*/ jsxRuntime.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
300
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Footer, {
|
|
301
|
+
children: [
|
|
302
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Cancel, {
|
|
303
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
304
|
+
variant: "tertiary",
|
|
305
|
+
disabled: isDeleting,
|
|
306
|
+
fullWidth: true,
|
|
307
|
+
children: formatMessage({
|
|
308
|
+
id: 'app.components.Button.cancel',
|
|
309
|
+
defaultMessage: 'Cancel'
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
}),
|
|
313
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Action, {
|
|
314
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
315
|
+
variant: "danger-light",
|
|
316
|
+
loading: isDeleting,
|
|
317
|
+
onClick: handleConfirm,
|
|
318
|
+
fullWidth: true,
|
|
319
|
+
children: formatMessage({
|
|
320
|
+
id: 'app.components.Button.confirm',
|
|
321
|
+
defaultMessage: 'Confirm'
|
|
322
|
+
})
|
|
323
|
+
})
|
|
324
|
+
})
|
|
325
|
+
]
|
|
234
326
|
})
|
|
235
327
|
]
|
|
328
|
+
})
|
|
329
|
+
]
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
const CopyLinkButton = ({ asset })=>{
|
|
333
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
334
|
+
const { copy } = strapiAdmin.useClipboard();
|
|
335
|
+
const notify = useDrawerNotify();
|
|
336
|
+
const handleCopy = async ()=>{
|
|
337
|
+
const url = files.prefixFileUrlWithBackendUrl(asset.url);
|
|
338
|
+
if (!url) return;
|
|
339
|
+
const didCopy = await copy(url);
|
|
340
|
+
notify({
|
|
341
|
+
type: didCopy ? 'success' : 'danger',
|
|
342
|
+
message: didCopy ? formatMessage({
|
|
343
|
+
id: translations.getTranslationKey('asset-details.copy-link.success'),
|
|
344
|
+
defaultMessage: 'Link copied.'
|
|
345
|
+
}) : formatMessage({
|
|
346
|
+
id: translations.getTranslationKey('asset-details.copy-link.error'),
|
|
347
|
+
defaultMessage: 'Failed to copy the link.'
|
|
348
|
+
})
|
|
349
|
+
});
|
|
350
|
+
};
|
|
351
|
+
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
|
352
|
+
withTooltip: false,
|
|
353
|
+
label: formatMessage({
|
|
354
|
+
id: translations.getTranslationKey('asset-details.copy-link.trigger'),
|
|
355
|
+
defaultMessage: 'Copy link'
|
|
356
|
+
}),
|
|
357
|
+
variant: "tertiary",
|
|
358
|
+
onClick: handleCopy,
|
|
359
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Link, {})
|
|
360
|
+
});
|
|
361
|
+
};
|
|
362
|
+
const DownloadAssetButton = ({ asset })=>{
|
|
363
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
364
|
+
const notify = useDrawerNotify();
|
|
365
|
+
const [isDownloading, setIsDownloading] = React__namespace.useState(false);
|
|
366
|
+
const handleDownload = async ()=>{
|
|
367
|
+
const url = files.prefixFileUrlWithBackendUrl(asset.url);
|
|
368
|
+
if (!url) return;
|
|
369
|
+
setIsDownloading(true);
|
|
370
|
+
try {
|
|
371
|
+
await downloadFile.downloadFile(url, asset.name);
|
|
372
|
+
} catch {
|
|
373
|
+
notify({
|
|
374
|
+
type: 'danger',
|
|
375
|
+
message: formatMessage({
|
|
376
|
+
id: translations.getTranslationKey('asset-details.download.error'),
|
|
377
|
+
defaultMessage: 'Failed to download the file.'
|
|
378
|
+
})
|
|
379
|
+
});
|
|
380
|
+
} finally{
|
|
381
|
+
setIsDownloading(false);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
|
385
|
+
withTooltip: false,
|
|
386
|
+
label: formatMessage({
|
|
387
|
+
id: translations.getTranslationKey('asset-details.download.trigger'),
|
|
388
|
+
defaultMessage: 'Download'
|
|
389
|
+
}),
|
|
390
|
+
variant: "tertiary",
|
|
391
|
+
onClick: handleDownload,
|
|
392
|
+
disabled: isDownloading,
|
|
393
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Download, {})
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
/* -------------------------------------------------------------------------------------------------
|
|
397
|
+
* ReplaceAssetButton
|
|
398
|
+
* -----------------------------------------------------------------------------------------------*/ const ReplaceAssetButton = ()=>{
|
|
399
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
400
|
+
const { replaceAsset, isReplacing } = useAssetOperation();
|
|
401
|
+
const fileInputRef = React__namespace.useRef(null);
|
|
402
|
+
const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
|
|
403
|
+
const { data: settings$1 } = settings.useGetSettingsQuery();
|
|
404
|
+
const aiEnabled = settings$1?.data?.aiMetadata ?? false;
|
|
405
|
+
const handleTriggerClick = ()=>{
|
|
406
|
+
setIsDialogOpen(true);
|
|
407
|
+
};
|
|
408
|
+
const handleContinue = ()=>{
|
|
409
|
+
// Confirm first, then open the native picker so the user only commits to
|
|
410
|
+
// replacing after acknowledging the warning. The actual POST is delegated
|
|
411
|
+
// to the parent (which owns the mutation + loading state).
|
|
412
|
+
setIsDialogOpen(false);
|
|
413
|
+
fileInputRef.current?.click();
|
|
414
|
+
};
|
|
415
|
+
const handleFileChange = async (event)=>{
|
|
416
|
+
const file = event.target.files?.[0];
|
|
417
|
+
// Reset the native input so the same file can be picked again later.
|
|
418
|
+
event.target.value = '';
|
|
419
|
+
if (!file) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
await replaceAsset(file);
|
|
423
|
+
};
|
|
424
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
425
|
+
children: [
|
|
426
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
|
|
427
|
+
children: /*#__PURE__*/ jsxRuntime.jsx("input", {
|
|
428
|
+
ref: fileInputRef,
|
|
429
|
+
type: "file",
|
|
430
|
+
multiple: false,
|
|
431
|
+
onChange: handleFileChange,
|
|
432
|
+
"aria-hidden": true,
|
|
433
|
+
tabIndex: -1
|
|
434
|
+
})
|
|
236
435
|
}),
|
|
237
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
238
|
-
|
|
436
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
|
437
|
+
withTooltip: false,
|
|
239
438
|
label: formatMessage({
|
|
240
|
-
id: translations.getTranslationKey('asset-details.
|
|
241
|
-
defaultMessage: '
|
|
439
|
+
id: translations.getTranslationKey('asset-details.replace.trigger'),
|
|
440
|
+
defaultMessage: 'Replace this file'
|
|
242
441
|
}),
|
|
243
|
-
|
|
244
|
-
|
|
442
|
+
variant: "tertiary",
|
|
443
|
+
onClick: handleTriggerClick,
|
|
444
|
+
disabled: isReplacing,
|
|
445
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(icons.ArrowsCounterClockwise, {})
|
|
245
446
|
}),
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
447
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
|
448
|
+
open: isDialogOpen,
|
|
449
|
+
onOpenChange: setIsDialogOpen,
|
|
450
|
+
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Content, {
|
|
451
|
+
children: [
|
|
452
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Header, {
|
|
453
|
+
children: formatMessage({
|
|
454
|
+
id: translations.getTranslationKey('asset-details.replace.title'),
|
|
455
|
+
defaultMessage: 'Replace this media file?'
|
|
456
|
+
})
|
|
253
457
|
}),
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
458
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Body, {
|
|
459
|
+
textAlign: "center",
|
|
460
|
+
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
461
|
+
direction: "column",
|
|
462
|
+
textAlign: "center",
|
|
463
|
+
children: [
|
|
464
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
465
|
+
variant: "omega",
|
|
466
|
+
children: formatMessage({
|
|
467
|
+
id: translations.getTranslationKey('asset-details.replace.description'),
|
|
468
|
+
defaultMessage: 'Current content will be permanently replaced.'
|
|
469
|
+
})
|
|
470
|
+
}),
|
|
471
|
+
aiEnabled ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
472
|
+
variant: "omega",
|
|
473
|
+
children: formatMessage({
|
|
474
|
+
id: translations.getTranslationKey('asset-details.replace.description.ai'),
|
|
475
|
+
defaultMessage: 'AI will generate new metadata after upload.'
|
|
476
|
+
})
|
|
477
|
+
}) : null
|
|
478
|
+
]
|
|
479
|
+
})
|
|
261
480
|
}),
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
481
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Footer, {
|
|
482
|
+
children: [
|
|
483
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Cancel, {
|
|
484
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
485
|
+
variant: "tertiary",
|
|
486
|
+
fullWidth: true,
|
|
487
|
+
children: formatMessage({
|
|
488
|
+
id: 'app.components.Button.cancel',
|
|
489
|
+
defaultMessage: 'Cancel'
|
|
490
|
+
})
|
|
491
|
+
})
|
|
492
|
+
}),
|
|
493
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Action, {
|
|
494
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
495
|
+
variant: "secondary",
|
|
496
|
+
onClick: handleContinue,
|
|
497
|
+
fullWidth: true,
|
|
498
|
+
children: formatMessage({
|
|
499
|
+
id: translations.getTranslationKey('asset-details.replace.continue'),
|
|
500
|
+
defaultMessage: 'Continue'
|
|
501
|
+
})
|
|
502
|
+
})
|
|
503
|
+
})
|
|
504
|
+
]
|
|
505
|
+
})
|
|
506
|
+
]
|
|
507
|
+
})
|
|
265
508
|
})
|
|
266
509
|
]
|
|
267
510
|
});
|
|
268
511
|
};
|
|
512
|
+
const AssetDetails = ({ asset, closeDetails })=>{
|
|
513
|
+
const { formatMessage, formatDate } = reactIntl.useIntl();
|
|
514
|
+
const { data: folders$1 = [] } = folders.useGetAllFoldersQuery();
|
|
515
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
|
516
|
+
const [updateAsset] = assets.useUpdateAssetMutation();
|
|
517
|
+
const [replaceMutation, { isLoading: isReplacing }] = assets.useReplaceAssetMutation();
|
|
518
|
+
const [deleteMutation, { isLoading: isDeleting }] = assets.useDeleteAssetMutation();
|
|
519
|
+
// In-drawer toast slot
|
|
520
|
+
const [drawerToast, setDrawerToast] = React__namespace.useState(null);
|
|
521
|
+
React__namespace.useEffect(()=>{
|
|
522
|
+
if (!drawerToast) return;
|
|
523
|
+
const timer = window.setTimeout(()=>setDrawerToast(null), 5000);
|
|
524
|
+
return ()=>window.clearTimeout(timer);
|
|
525
|
+
}, [
|
|
526
|
+
drawerToast
|
|
527
|
+
]);
|
|
528
|
+
// Local alias matching the DrawerNotifyContext signature, so the drawer's
|
|
529
|
+
// own handlers (replace, update) read like the consumers do.
|
|
530
|
+
const notify = React__namespace.useCallback((toast)=>setDrawerToast(toast), []);
|
|
531
|
+
const isImage = asset.mime?.includes(enums.AssetType.Image);
|
|
532
|
+
const initialValues = {
|
|
533
|
+
name: asset.name ?? '',
|
|
534
|
+
caption: asset.caption ?? '',
|
|
535
|
+
alternativeText: asset.alternativeText ?? '',
|
|
536
|
+
folder: typeof asset.folder === 'object' && asset.folder !== null ? asset.folder.id ?? null : asset.folder ?? null
|
|
537
|
+
};
|
|
538
|
+
const handleSubmit = async (values)=>{
|
|
539
|
+
const res = await updateAsset({
|
|
540
|
+
id: asset.id,
|
|
541
|
+
fileInfo: {
|
|
542
|
+
name: values.name,
|
|
543
|
+
caption: values.caption,
|
|
544
|
+
alternativeText: values.alternativeText,
|
|
545
|
+
folder: values.folder
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
if ('error' in res) {
|
|
549
|
+
notify({
|
|
550
|
+
type: 'danger',
|
|
551
|
+
message: formatMessage({
|
|
552
|
+
id: translations.getTranslationKey('asset-details.update.error'),
|
|
553
|
+
defaultMessage: 'Failed to update the file.'
|
|
554
|
+
})
|
|
555
|
+
});
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
notify({
|
|
559
|
+
type: 'success',
|
|
560
|
+
message: formatMessage({
|
|
561
|
+
id: translations.getTranslationKey('asset-details.update.success'),
|
|
562
|
+
defaultMessage: 'File updated'
|
|
563
|
+
})
|
|
564
|
+
});
|
|
565
|
+
};
|
|
566
|
+
const { title: folderName } = useFolderInfo.useFolderInfo(typeof asset.folder === 'object' && asset.folder !== null ? asset.folder.id ?? null : asset.folder ?? null);
|
|
567
|
+
// Owns the replace upload so isReplacing can drive the busy overlay.
|
|
568
|
+
const handleReplace = async (file)=>{
|
|
569
|
+
const res = await replaceMutation({
|
|
570
|
+
id: asset.id,
|
|
571
|
+
file
|
|
572
|
+
});
|
|
573
|
+
if ('error' in res) {
|
|
574
|
+
const error = res.error;
|
|
575
|
+
const message = error?.data?.error?.message ?? error?.data?.message ?? formatMessage({
|
|
576
|
+
id: translations.getTranslationKey('asset-details.replace.error'),
|
|
577
|
+
defaultMessage: 'Failed to replace the file.'
|
|
578
|
+
});
|
|
579
|
+
notify({
|
|
580
|
+
type: 'danger',
|
|
581
|
+
message
|
|
582
|
+
});
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
notify({
|
|
586
|
+
type: 'success',
|
|
587
|
+
message: formatMessage({
|
|
588
|
+
id: translations.getTranslationKey('asset-details.replace.success'),
|
|
589
|
+
defaultMessage: 'File replaced.'
|
|
590
|
+
})
|
|
591
|
+
});
|
|
592
|
+
};
|
|
593
|
+
// Owns the delete: on error notify in-drawer (drawer stays), on success fire
|
|
594
|
+
// a persistent global notification then close the drawer.
|
|
595
|
+
const handleDelete = async ()=>{
|
|
596
|
+
const res = await deleteMutation(asset.id);
|
|
597
|
+
if ('error' in res) {
|
|
598
|
+
const error = res.error;
|
|
599
|
+
const message = error?.data?.error?.message ?? error?.data?.message ?? formatMessage({
|
|
600
|
+
id: translations.getTranslationKey('asset-details.delete.error'),
|
|
601
|
+
defaultMessage: 'Failed to delete the asset.'
|
|
602
|
+
});
|
|
603
|
+
notify({
|
|
604
|
+
type: 'danger',
|
|
605
|
+
message
|
|
606
|
+
});
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
toggleNotification({
|
|
610
|
+
type: 'success',
|
|
611
|
+
message: formatMessage({
|
|
612
|
+
id: translations.getTranslationKey('asset-details.delete.success'),
|
|
613
|
+
defaultMessage: '1 element have been deleted from {folderName}'
|
|
614
|
+
}, {
|
|
615
|
+
folderName
|
|
616
|
+
})
|
|
617
|
+
});
|
|
618
|
+
closeDetails();
|
|
619
|
+
};
|
|
620
|
+
const operations = React__namespace.useMemo(()=>({
|
|
621
|
+
replaceAsset: handleReplace,
|
|
622
|
+
deleteAsset: handleDelete,
|
|
623
|
+
isReplacing,
|
|
624
|
+
isDeleting
|
|
625
|
+
}), // handleReplace / handleDelete close over asset+mutations and don't need a
|
|
626
|
+
// stable identity here; the consumers re-render with the new context value.
|
|
627
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
628
|
+
[
|
|
629
|
+
isReplacing,
|
|
630
|
+
isDeleting
|
|
631
|
+
]);
|
|
632
|
+
return(// `key={asset.id}` resets the form when the drawer switches to a different
|
|
633
|
+
// asset so cached values from the previous asset don't bleed in.
|
|
634
|
+
/*#__PURE__*/ jsxRuntime.jsx(DrawerNotifyContext.Provider, {
|
|
635
|
+
value: notify,
|
|
636
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(AssetOperationsContext.Provider, {
|
|
637
|
+
value: operations,
|
|
638
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(FormShell, {
|
|
639
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Form, {
|
|
640
|
+
method: "POST",
|
|
641
|
+
initialValues: initialValues,
|
|
642
|
+
onSubmit: handleSubmit,
|
|
643
|
+
children: ({ modified, isSubmitting, values, resetForm })=>{
|
|
644
|
+
const nameIsEmpty = (values.name ?? '').trim() === '';
|
|
645
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
646
|
+
children: [
|
|
647
|
+
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Blocker, {
|
|
648
|
+
onProceed: resetForm
|
|
649
|
+
}),
|
|
650
|
+
isReplacing || isDeleting ? /*#__PURE__*/ jsxRuntime.jsx(DrawerBusyOverlay, {
|
|
651
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Loader, {
|
|
652
|
+
children: formatMessage({
|
|
653
|
+
id: translations.getTranslationKey(isDeleting ? 'asset-details.delete.loading' : 'asset-details.replace.loading'),
|
|
654
|
+
defaultMessage: isDeleting ? 'Deleting the file…' : 'Replacing the file…'
|
|
655
|
+
})
|
|
656
|
+
})
|
|
657
|
+
}) : null,
|
|
658
|
+
drawerToast ? /*#__PURE__*/ jsxRuntime.jsx(DrawerToastSlot, {
|
|
659
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Alert, {
|
|
660
|
+
variant: drawerToast.type === 'success' ? 'success' : 'danger',
|
|
661
|
+
closeLabel: formatMessage({
|
|
662
|
+
id: 'global.close',
|
|
663
|
+
defaultMessage: 'Close'
|
|
664
|
+
}),
|
|
665
|
+
onClose: ()=>setDrawerToast(null),
|
|
666
|
+
children: drawerToast.message
|
|
667
|
+
})
|
|
668
|
+
}) : null,
|
|
669
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Drawer.Drawer.ScrollableContent, {
|
|
670
|
+
children: [
|
|
671
|
+
/*#__PURE__*/ jsxRuntime.jsx(AssetPreview.AssetPreview, {
|
|
672
|
+
asset: asset,
|
|
673
|
+
actions: isImage ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
674
|
+
direction: "column",
|
|
675
|
+
gap: 2,
|
|
676
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(ReplaceAssetButton, {})
|
|
677
|
+
}) : null
|
|
678
|
+
}),
|
|
679
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
680
|
+
direction: "column",
|
|
681
|
+
alignItems: "stretch",
|
|
682
|
+
gap: 4,
|
|
683
|
+
paddingTop: 4,
|
|
684
|
+
paddingBottom: 4,
|
|
685
|
+
paddingLeft: 5,
|
|
686
|
+
paddingRight: 5,
|
|
687
|
+
children: [
|
|
688
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
689
|
+
variant: "beta",
|
|
690
|
+
fontWeight: "semiBold",
|
|
691
|
+
tag: "h3",
|
|
692
|
+
children: formatMessage({
|
|
693
|
+
id: translations.getTranslationKey('asset-details.fileInfo'),
|
|
694
|
+
defaultMessage: 'File info'
|
|
695
|
+
})
|
|
696
|
+
}),
|
|
697
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
698
|
+
wrap: "wrap",
|
|
699
|
+
gap: 4,
|
|
700
|
+
background: "neutral100",
|
|
701
|
+
paddingTop: 4,
|
|
702
|
+
paddingBottom: 4,
|
|
703
|
+
paddingLeft: 6,
|
|
704
|
+
paddingRight: 6,
|
|
705
|
+
alignItems: "flex-start",
|
|
706
|
+
children: [
|
|
707
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
708
|
+
label: formatMessage({
|
|
709
|
+
id: translations.getTranslationKey('asset-details.creationDate'),
|
|
710
|
+
defaultMessage: 'Creation date'
|
|
711
|
+
}),
|
|
712
|
+
value: asset.createdAt ? formatDate(new Date(asset.createdAt), {
|
|
713
|
+
dateStyle: 'long',
|
|
714
|
+
timeStyle: 'short'
|
|
715
|
+
}) : null
|
|
716
|
+
}),
|
|
717
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
718
|
+
label: formatMessage({
|
|
719
|
+
id: translations.getTranslationKey('asset-details.lastUpdated'),
|
|
720
|
+
defaultMessage: 'Last updated'
|
|
721
|
+
}),
|
|
722
|
+
value: asset.updatedAt ? formatDate(new Date(asset.updatedAt), {
|
|
723
|
+
dateStyle: 'long',
|
|
724
|
+
timeStyle: 'short'
|
|
725
|
+
}) : null
|
|
726
|
+
}),
|
|
727
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
728
|
+
label: formatMessage({
|
|
729
|
+
id: translations.getTranslationKey('asset-details.createdBy'),
|
|
730
|
+
defaultMessage: 'Created by'
|
|
731
|
+
}),
|
|
732
|
+
value: asset.createdBy ? strapiAdmin.getDisplayName({
|
|
733
|
+
firstname: asset.createdBy.firstname ?? undefined,
|
|
734
|
+
lastname: asset.createdBy.lastname ?? undefined,
|
|
735
|
+
username: asset.createdBy.username ?? undefined,
|
|
736
|
+
email: asset.createdBy.email ?? undefined
|
|
737
|
+
}) ?? '-' : null
|
|
738
|
+
}),
|
|
739
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
740
|
+
label: formatMessage({
|
|
741
|
+
id: translations.getTranslationKey('asset-details.size'),
|
|
742
|
+
defaultMessage: 'Size'
|
|
743
|
+
}),
|
|
744
|
+
value: asset.size ? files.formatBytes(asset.size, 1) : null
|
|
745
|
+
}),
|
|
746
|
+
isImage && (asset.width != null || asset.height != null) && /*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
747
|
+
label: formatMessage({
|
|
748
|
+
id: translations.getTranslationKey('asset-details.dimensions'),
|
|
749
|
+
defaultMessage: 'Dimensions'
|
|
750
|
+
}),
|
|
751
|
+
value: asset.width != null && asset.height != null ? `${asset.width} × ${asset.height}` : null
|
|
752
|
+
}),
|
|
753
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
754
|
+
label: formatMessage({
|
|
755
|
+
id: translations.getTranslationKey('asset-details.extension'),
|
|
756
|
+
defaultMessage: 'Extension'
|
|
757
|
+
}),
|
|
758
|
+
value: files.getFileExtension(asset.ext)
|
|
759
|
+
}),
|
|
760
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailItem, {
|
|
761
|
+
label: formatMessage({
|
|
762
|
+
id: translations.getTranslationKey('asset-details.assetId'),
|
|
763
|
+
defaultMessage: 'Asset ID'
|
|
764
|
+
}),
|
|
765
|
+
value: String(asset.id)
|
|
766
|
+
})
|
|
767
|
+
]
|
|
768
|
+
}),
|
|
769
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailField, {
|
|
770
|
+
name: "name",
|
|
771
|
+
label: formatMessage({
|
|
772
|
+
id: translations.getTranslationKey('asset-details.fileName'),
|
|
773
|
+
defaultMessage: 'File name'
|
|
774
|
+
}),
|
|
775
|
+
required: true
|
|
776
|
+
}),
|
|
777
|
+
/*#__PURE__*/ jsxRuntime.jsx(LocationField, {
|
|
778
|
+
label: formatMessage({
|
|
779
|
+
id: translations.getTranslationKey('asset-details.location'),
|
|
780
|
+
defaultMessage: 'Location'
|
|
781
|
+
}),
|
|
782
|
+
rootLabel: formatMessage({
|
|
783
|
+
id: translations.getTranslationKey('plugin.home'),
|
|
784
|
+
defaultMessage: 'Home'
|
|
785
|
+
}),
|
|
786
|
+
folders: folders$1
|
|
787
|
+
}),
|
|
788
|
+
isImage && /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
789
|
+
children: [
|
|
790
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailField, {
|
|
791
|
+
name: "caption",
|
|
792
|
+
label: formatMessage({
|
|
793
|
+
id: translations.getTranslationKey('asset-details.caption'),
|
|
794
|
+
defaultMessage: 'Caption'
|
|
795
|
+
})
|
|
796
|
+
}),
|
|
797
|
+
/*#__PURE__*/ jsxRuntime.jsx(DetailField, {
|
|
798
|
+
name: "alternativeText",
|
|
799
|
+
label: formatMessage({
|
|
800
|
+
id: translations.getTranslationKey('asset-details.alternativeText'),
|
|
801
|
+
defaultMessage: 'Alternative text'
|
|
802
|
+
})
|
|
803
|
+
})
|
|
804
|
+
]
|
|
805
|
+
})
|
|
806
|
+
]
|
|
807
|
+
})
|
|
808
|
+
]
|
|
809
|
+
}),
|
|
810
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
811
|
+
justifyContent: "space-between",
|
|
812
|
+
alignItems: "center",
|
|
813
|
+
gap: 2,
|
|
814
|
+
padding: 3,
|
|
815
|
+
borderColor: "neutral150",
|
|
816
|
+
borderStyle: "solid",
|
|
817
|
+
borderWidth: "1px 0 0 0",
|
|
818
|
+
background: "neutral0",
|
|
819
|
+
children: [
|
|
820
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
821
|
+
gap: 2,
|
|
822
|
+
children: [
|
|
823
|
+
/*#__PURE__*/ jsxRuntime.jsx(DeleteAssetButton, {}),
|
|
824
|
+
/*#__PURE__*/ jsxRuntime.jsx(CopyLinkButton, {
|
|
825
|
+
asset: asset
|
|
826
|
+
}),
|
|
827
|
+
/*#__PURE__*/ jsxRuntime.jsx(DownloadAssetButton, {
|
|
828
|
+
asset: asset
|
|
829
|
+
})
|
|
830
|
+
]
|
|
831
|
+
}),
|
|
832
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
833
|
+
type: "submit",
|
|
834
|
+
variant: "default",
|
|
835
|
+
loading: isSubmitting,
|
|
836
|
+
// File name is required; block submit when it's empty or whitespace so the API can't 400 on a blank value.
|
|
837
|
+
disabled: !modified || isSubmitting || nameIsEmpty,
|
|
838
|
+
children: formatMessage({
|
|
839
|
+
id: translations.getTranslationKey('asset-details.save'),
|
|
840
|
+
defaultMessage: 'Save changes'
|
|
841
|
+
})
|
|
842
|
+
})
|
|
843
|
+
]
|
|
844
|
+
})
|
|
845
|
+
]
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
}, asset.id)
|
|
849
|
+
})
|
|
850
|
+
})
|
|
851
|
+
}));
|
|
852
|
+
};
|
|
269
853
|
const DrawerHeader = ({ asset, closeDetails })=>{
|
|
270
854
|
const DocIcon = asset ? getAssetIcon.getAssetIcon(asset.mime, asset.ext) : icons.FileError;
|
|
271
855
|
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
@@ -274,6 +858,9 @@ const DrawerHeader = ({ asset, closeDetails })=>{
|
|
|
274
858
|
paddingTop: 3,
|
|
275
859
|
paddingBottom: 3,
|
|
276
860
|
paddingRight: 3,
|
|
861
|
+
borderColor: "neutral150",
|
|
862
|
+
borderStyle: "solid",
|
|
863
|
+
borderWidth: "0 0 1px 0",
|
|
277
864
|
children: [
|
|
278
865
|
/*#__PURE__*/ jsxRuntime.jsx(DocIcon, {
|
|
279
866
|
width: 20,
|
|
@@ -345,15 +932,9 @@ const DrawerContent = ({ assetId, closeDetails })=>{
|
|
|
345
932
|
asset: asset,
|
|
346
933
|
closeDetails: closeDetails
|
|
347
934
|
}),
|
|
348
|
-
/*#__PURE__*/ jsxRuntime.
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
asset: asset
|
|
352
|
-
}),
|
|
353
|
-
/*#__PURE__*/ jsxRuntime.jsx(AssetDetails, {
|
|
354
|
-
asset: asset
|
|
355
|
-
})
|
|
356
|
-
]
|
|
935
|
+
/*#__PURE__*/ jsxRuntime.jsx(AssetDetails, {
|
|
936
|
+
asset: asset,
|
|
937
|
+
closeDetails: closeDetails
|
|
357
938
|
})
|
|
358
939
|
]
|
|
359
940
|
});
|
|
@@ -362,7 +943,7 @@ const DrawerContent = ({ assetId, closeDetails })=>{
|
|
|
362
943
|
* AssetDetailsDrawer
|
|
363
944
|
* -----------------------------------------------------------------------------------------------*/ const AssetDetailsDrawer = ()=>{
|
|
364
945
|
const { formatMessage } = reactIntl.useIntl();
|
|
365
|
-
const { assetId, isVisible, shouldRenderDrawer, closeDetails } = useAssetDetailsParam();
|
|
946
|
+
const { assetId, isVisible, shouldRenderDrawer, onCloseAnimationEnd, closeDetails } = useAssetDetailsParam();
|
|
366
947
|
if (!shouldRenderDrawer || assetId === null) {
|
|
367
948
|
return null;
|
|
368
949
|
}
|
|
@@ -392,6 +973,7 @@ const DrawerContent = ({ assetId, closeDetails })=>{
|
|
|
392
973
|
animationDirection: "left",
|
|
393
974
|
width: "41.6rem",
|
|
394
975
|
height: "100vh",
|
|
976
|
+
onAnimationEnd: onCloseAnimationEnd,
|
|
395
977
|
children: /*#__PURE__*/ jsxRuntime.jsx(DrawerContent, {
|
|
396
978
|
assetId: assetId,
|
|
397
979
|
closeDetails: closeDetails
|
|
@@ -401,6 +983,9 @@ const DrawerContent = ({ assetId, closeDetails })=>{
|
|
|
401
983
|
});
|
|
402
984
|
};
|
|
403
985
|
|
|
986
|
+
exports.AssetDetails = AssetDetails;
|
|
404
987
|
exports.AssetDetailsDrawer = AssetDetailsDrawer;
|
|
988
|
+
exports.AssetOperationsContext = AssetOperationsContext;
|
|
989
|
+
exports.DrawerNotifyContext = DrawerNotifyContext;
|
|
405
990
|
exports.useAssetDetailsParam = useAssetDetailsParam;
|
|
406
991
|
//# sourceMappingURL=AssetDetailsDrawer.js.map
|