@firecms/media_manager 3.1.0-canary.02232f4
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/LICENSE +6 -0
- package/dist/MediaManagerProvider.d.ts +14 -0
- package/dist/components/MediaAssetCard.d.ts +13 -0
- package/dist/components/MediaAssetDetails.d.ts +11 -0
- package/dist/components/MediaLibraryCard.d.ts +8 -0
- package/dist/components/MediaLibraryView.d.ts +9 -0
- package/dist/components/MediaUploadDialog.d.ts +13 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.es.js +1741 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +1737 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/locales/de.d.ts +45 -0
- package/dist/locales/en.d.ts +45 -0
- package/dist/locales/es.d.ts +45 -0
- package/dist/locales/fr.d.ts +45 -0
- package/dist/locales/hi.d.ts +45 -0
- package/dist/locales/it.d.ts +45 -0
- package/dist/locales/pt.d.ts +45 -0
- package/dist/types/config.d.ts +87 -0
- package/dist/types/controller.d.ts +66 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/media_asset.d.ts +70 -0
- package/dist/useMediaManagerController.d.ts +18 -0
- package/dist/useMediaManagerPlugin.d.ts +23 -0
- package/package.json +58 -0
- package/src/MediaManagerProvider.tsx +34 -0
- package/src/components/MediaAssetCard.tsx +134 -0
- package/src/components/MediaAssetDetails.tsx +353 -0
- package/src/components/MediaLibraryCard.tsx +58 -0
- package/src/components/MediaLibraryView.tsx +196 -0
- package/src/components/MediaUploadDialog.tsx +266 -0
- package/src/components/index.ts +5 -0
- package/src/index.ts +10 -0
- package/src/locales/de.ts +45 -0
- package/src/locales/en.ts +45 -0
- package/src/locales/es.ts +45 -0
- package/src/locales/fr.ts +45 -0
- package/src/locales/hi.ts +45 -0
- package/src/locales/it.ts +45 -0
- package/src/locales/pt.ts +45 -0
- package/src/types/config.ts +100 -0
- package/src/types/controller.ts +79 -0
- package/src/types/index.ts +3 -0
- package/src/types/media_asset.ts +84 -0
- package/src/useMediaManagerController.tsx +387 -0
- package/src/useMediaManagerPlugin.tsx +114 -0
|
@@ -0,0 +1,1737 @@
|
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("react-compiler-runtime"), require("react"), require("compressorjs"), require("@firecms/ui"), require("@firecms/core"), require("@firecms/formex"), require("react-router-dom")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "react-compiler-runtime", "react", "compressorjs", "@firecms/ui", "@firecms/core", "@firecms/formex", "react-router-dom"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.FireCMSMediaManager = {}, global.jsxRuntime, global.reactCompilerRuntime, global.react, global.Compressor, global.ui, global.core, global.formex, global.reactRouterDom));
|
|
3
|
+
})(this, (function(exports2, jsxRuntime, reactCompilerRuntime, react, Compressor, ui, core, formex, reactRouterDom) {
|
|
4
|
+
"use strict";
|
|
5
|
+
const MediaManagerContext = react.createContext(void 0);
|
|
6
|
+
function useMediaManager() {
|
|
7
|
+
const context = react.useContext(MediaManagerContext);
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw new Error("useMediaManager must be used within a MediaManagerProvider");
|
|
10
|
+
}
|
|
11
|
+
return context;
|
|
12
|
+
}
|
|
13
|
+
function MediaManagerProvider(t0) {
|
|
14
|
+
const $ = reactCompilerRuntime.c(3);
|
|
15
|
+
const {
|
|
16
|
+
controller,
|
|
17
|
+
children
|
|
18
|
+
} = t0;
|
|
19
|
+
let t1;
|
|
20
|
+
if ($[0] !== children || $[1] !== controller) {
|
|
21
|
+
t1 = /* @__PURE__ */ jsxRuntime.jsx(MediaManagerContext.Provider, { value: controller, children });
|
|
22
|
+
$[0] = children;
|
|
23
|
+
$[1] = controller;
|
|
24
|
+
$[2] = t1;
|
|
25
|
+
} else {
|
|
26
|
+
t1 = $[2];
|
|
27
|
+
}
|
|
28
|
+
return t1;
|
|
29
|
+
}
|
|
30
|
+
const DEFAULT_THUMBNAIL_PATH = "thumbs";
|
|
31
|
+
function useMediaManagerController({
|
|
32
|
+
storageSource,
|
|
33
|
+
dataSourceDelegate,
|
|
34
|
+
storagePath,
|
|
35
|
+
collectionPath,
|
|
36
|
+
bucket,
|
|
37
|
+
thumbnailSizes,
|
|
38
|
+
thumbnailPath = DEFAULT_THUMBNAIL_PATH
|
|
39
|
+
}) {
|
|
40
|
+
const [loading, setLoading] = react.useState(true);
|
|
41
|
+
const [error, setError] = react.useState();
|
|
42
|
+
const [assets, setAssets] = react.useState([]);
|
|
43
|
+
const [selectedAsset, setSelectedAsset] = react.useState();
|
|
44
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
45
|
+
const fetchDownloadURL = react.useCallback(async (asset) => {
|
|
46
|
+
try {
|
|
47
|
+
const downloadConfig = await storageSource.getDownloadURL(asset.storagePath, asset.bucket);
|
|
48
|
+
return {
|
|
49
|
+
...asset,
|
|
50
|
+
downloadURL: downloadConfig.url ?? void 0
|
|
51
|
+
};
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.warn(`Failed to get download URL for ${asset.storagePath}:`, err);
|
|
54
|
+
return {
|
|
55
|
+
...asset,
|
|
56
|
+
downloadURL: void 0
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}, [storageSource]);
|
|
60
|
+
const refreshAssets = react.useCallback(async () => {
|
|
61
|
+
setLoading(true);
|
|
62
|
+
setError(void 0);
|
|
63
|
+
try {
|
|
64
|
+
console.log("Fetching media assets from:", collectionPath);
|
|
65
|
+
const entities = await dataSourceDelegate.fetchCollection({
|
|
66
|
+
path: collectionPath,
|
|
67
|
+
orderBy: "createdAt",
|
|
68
|
+
order: "desc"
|
|
69
|
+
});
|
|
70
|
+
console.log("Fetched entities:", entities.length);
|
|
71
|
+
if (entities.length === 0) {
|
|
72
|
+
setAssets([]);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const loadedAssets = await Promise.all(entities.map(async (entity) => {
|
|
76
|
+
const values = entity.values;
|
|
77
|
+
const baseAsset = {
|
|
78
|
+
id: entity.id,
|
|
79
|
+
fileName: values.fileName,
|
|
80
|
+
storagePath: values.storagePath,
|
|
81
|
+
mimeType: values.mimeType,
|
|
82
|
+
size: values.size,
|
|
83
|
+
dimensions: values.dimensions,
|
|
84
|
+
title: values.title,
|
|
85
|
+
altText: values.altText,
|
|
86
|
+
caption: values.caption,
|
|
87
|
+
tags: values.tags,
|
|
88
|
+
bucket: values.bucket,
|
|
89
|
+
createdAt: values.createdAt instanceof Date ? values.createdAt : values.createdAt?.toDate ? values.createdAt.toDate() : new Date(values.createdAt),
|
|
90
|
+
updatedAt: values.updatedAt instanceof Date ? values.updatedAt : values.updatedAt?.toDate ? values.updatedAt.toDate() : new Date(values.updatedAt)
|
|
91
|
+
};
|
|
92
|
+
if (baseAsset.mimeType?.startsWith("image/") || baseAsset.mimeType?.startsWith("video/")) {
|
|
93
|
+
return await fetchDownloadURL(baseAsset);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
...baseAsset,
|
|
97
|
+
downloadURL: void 0
|
|
98
|
+
};
|
|
99
|
+
}));
|
|
100
|
+
console.log("Loaded assets with URLs:", loadedAssets.length);
|
|
101
|
+
setAssets(loadedAssets);
|
|
102
|
+
} catch (err_0) {
|
|
103
|
+
console.error("Error fetching media assets:", err_0);
|
|
104
|
+
setError(err_0 instanceof Error ? err_0 : new Error(String(err_0)));
|
|
105
|
+
} finally {
|
|
106
|
+
setLoading(false);
|
|
107
|
+
}
|
|
108
|
+
}, [dataSourceDelegate, collectionPath, fetchDownloadURL]);
|
|
109
|
+
react.useEffect(() => {
|
|
110
|
+
refreshAssets();
|
|
111
|
+
}, [refreshAssets]);
|
|
112
|
+
const uploadFile = react.useCallback(async (file, metadata) => {
|
|
113
|
+
console.log("Uploading file:", file.name, "to path:", storagePath);
|
|
114
|
+
const uploadResult = await storageSource.uploadFile({
|
|
115
|
+
file,
|
|
116
|
+
fileName: file.name,
|
|
117
|
+
path: storagePath,
|
|
118
|
+
bucket
|
|
119
|
+
});
|
|
120
|
+
console.log("Upload result:", uploadResult);
|
|
121
|
+
let downloadURL;
|
|
122
|
+
try {
|
|
123
|
+
const downloadConfig_0 = await storageSource.getDownloadURL(uploadResult.path, uploadResult.bucket);
|
|
124
|
+
downloadURL = downloadConfig_0.url ?? void 0;
|
|
125
|
+
console.log("Got download URL:", downloadURL);
|
|
126
|
+
} catch (err_1) {
|
|
127
|
+
console.warn("Failed to get download URL after upload:", err_1);
|
|
128
|
+
}
|
|
129
|
+
let dimensions;
|
|
130
|
+
if (file.type.startsWith("image/")) {
|
|
131
|
+
try {
|
|
132
|
+
dimensions = await getImageDimensions(file);
|
|
133
|
+
} catch (err_2) {
|
|
134
|
+
console.warn("Failed to get image dimensions:", err_2);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const thumbnails = {};
|
|
138
|
+
const isRasterImage = file.type.startsWith("image/") && file.type !== "image/svg+xml";
|
|
139
|
+
if (thumbnailSizes && thumbnailSizes.length > 0 && isRasterImage) {
|
|
140
|
+
console.log("Generating thumbnails for sizes:", thumbnailSizes.map((s) => s.name));
|
|
141
|
+
for (const size of thumbnailSizes) {
|
|
142
|
+
try {
|
|
143
|
+
const thumbnailBlob = await generateThumbnail(file, size.width, size.height, size.quality ?? 0.8);
|
|
144
|
+
const thumbFileName = `${Date.now()}_${size.name}_${file.name}`;
|
|
145
|
+
const thumbPath = `${storagePath}/${thumbnailPath}/${size.name}`;
|
|
146
|
+
const thumbUploadResult = await storageSource.uploadFile({
|
|
147
|
+
file: new File([thumbnailBlob], thumbFileName, {
|
|
148
|
+
type: "image/jpeg"
|
|
149
|
+
}),
|
|
150
|
+
fileName: thumbFileName,
|
|
151
|
+
path: thumbPath,
|
|
152
|
+
bucket
|
|
153
|
+
});
|
|
154
|
+
const thumbDownloadConfig = await storageSource.getDownloadURL(thumbUploadResult.path, thumbUploadResult.bucket);
|
|
155
|
+
if (thumbDownloadConfig.url) {
|
|
156
|
+
thumbnails[size.name] = thumbDownloadConfig.url;
|
|
157
|
+
console.log(`Generated ${size.name} thumbnail:`, thumbDownloadConfig.url);
|
|
158
|
+
}
|
|
159
|
+
} catch (err_3) {
|
|
160
|
+
console.warn(`Failed to generate ${size.name} thumbnail:`, err_3);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const now = /* @__PURE__ */ new Date();
|
|
165
|
+
const assetData = {
|
|
166
|
+
fileName: file.name,
|
|
167
|
+
storagePath: uploadResult.path,
|
|
168
|
+
mimeType: file.type,
|
|
169
|
+
size: file.size,
|
|
170
|
+
createdAt: now,
|
|
171
|
+
updatedAt: now
|
|
172
|
+
};
|
|
173
|
+
if (dimensions) assetData.dimensions = dimensions;
|
|
174
|
+
if (metadata?.title) assetData.title = metadata.title;
|
|
175
|
+
if (metadata?.altText) assetData.altText = metadata.altText;
|
|
176
|
+
if (metadata?.caption) assetData.caption = metadata.caption;
|
|
177
|
+
if (metadata?.tags && metadata.tags.length > 0) assetData.tags = metadata.tags;
|
|
178
|
+
if (uploadResult.bucket) assetData.bucket = uploadResult.bucket;
|
|
179
|
+
if (downloadURL) assetData.downloadURL = downloadURL;
|
|
180
|
+
if (Object.keys(thumbnails).length > 0) assetData.thumbnails = thumbnails;
|
|
181
|
+
console.log("Saving asset data to database:", assetData);
|
|
182
|
+
const entity_0 = await dataSourceDelegate.saveEntity({
|
|
183
|
+
path: collectionPath,
|
|
184
|
+
values: assetData,
|
|
185
|
+
status: "new"
|
|
186
|
+
});
|
|
187
|
+
console.log("Saved entity:", entity_0.id);
|
|
188
|
+
const newAsset = {
|
|
189
|
+
id: entity_0.id,
|
|
190
|
+
fileName: file.name,
|
|
191
|
+
storagePath: uploadResult.path,
|
|
192
|
+
downloadURL,
|
|
193
|
+
mimeType: file.type,
|
|
194
|
+
size: file.size,
|
|
195
|
+
createdAt: now,
|
|
196
|
+
updatedAt: now,
|
|
197
|
+
dimensions,
|
|
198
|
+
title: metadata?.title,
|
|
199
|
+
altText: metadata?.altText,
|
|
200
|
+
caption: metadata?.caption,
|
|
201
|
+
tags: metadata?.tags,
|
|
202
|
+
bucket: uploadResult.bucket,
|
|
203
|
+
thumbnails: Object.keys(thumbnails).length > 0 ? thumbnails : void 0
|
|
204
|
+
};
|
|
205
|
+
setAssets((prev) => [newAsset, ...prev]);
|
|
206
|
+
return newAsset;
|
|
207
|
+
}, [storageSource, dataSourceDelegate, storagePath, collectionPath, bucket, thumbnailSizes, thumbnailPath]);
|
|
208
|
+
const deleteAsset = react.useCallback(async (assetId) => {
|
|
209
|
+
const asset_0 = assets.find((a) => a.id === assetId);
|
|
210
|
+
if (!asset_0) {
|
|
211
|
+
throw new Error(`Asset with id ${assetId} not found`);
|
|
212
|
+
}
|
|
213
|
+
console.log("Deleting asset:", assetId, asset_0.storagePath);
|
|
214
|
+
try {
|
|
215
|
+
await storageSource.deleteFile(asset_0.storagePath, asset_0.bucket);
|
|
216
|
+
} catch (err_4) {
|
|
217
|
+
console.warn("Failed to delete from storage (may not exist):", err_4);
|
|
218
|
+
}
|
|
219
|
+
await dataSourceDelegate.deleteEntity({
|
|
220
|
+
entity: {
|
|
221
|
+
id: assetId,
|
|
222
|
+
path: collectionPath,
|
|
223
|
+
values: asset_0
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
setAssets((prev_0) => prev_0.filter((a_0) => a_0.id !== assetId));
|
|
227
|
+
if (selectedAsset?.id === assetId) {
|
|
228
|
+
setSelectedAsset(void 0);
|
|
229
|
+
}
|
|
230
|
+
}, [assets, storageSource, dataSourceDelegate, collectionPath, selectedAsset]);
|
|
231
|
+
const updateAsset = react.useCallback(async (assetId_0, data) => {
|
|
232
|
+
const asset_1 = assets.find((a_1) => a_1.id === assetId_0);
|
|
233
|
+
if (!asset_1) {
|
|
234
|
+
throw new Error(`Asset with id ${assetId_0} not found`);
|
|
235
|
+
}
|
|
236
|
+
const cleanData = {};
|
|
237
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
238
|
+
if (value !== void 0) {
|
|
239
|
+
cleanData[key] = value;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
cleanData.updatedAt = /* @__PURE__ */ new Date();
|
|
243
|
+
console.log("Updating asset:", assetId_0, cleanData);
|
|
244
|
+
await dataSourceDelegate.saveEntity({
|
|
245
|
+
path: collectionPath,
|
|
246
|
+
entityId: assetId_0,
|
|
247
|
+
values: cleanData,
|
|
248
|
+
previousValues: asset_1,
|
|
249
|
+
status: "existing"
|
|
250
|
+
});
|
|
251
|
+
setAssets((prev_1) => prev_1.map((a_2) => a_2.id === assetId_0 ? {
|
|
252
|
+
...a_2,
|
|
253
|
+
...cleanData
|
|
254
|
+
} : a_2));
|
|
255
|
+
if (selectedAsset?.id === assetId_0) {
|
|
256
|
+
setSelectedAsset((prev_2) => prev_2 ? {
|
|
257
|
+
...prev_2,
|
|
258
|
+
...cleanData
|
|
259
|
+
} : prev_2);
|
|
260
|
+
}
|
|
261
|
+
}, [assets, dataSourceDelegate, collectionPath, selectedAsset]);
|
|
262
|
+
const searchAssets = react.useCallback((query) => {
|
|
263
|
+
setSearchQuery(query);
|
|
264
|
+
}, []);
|
|
265
|
+
const selectAsset = react.useCallback((asset_2) => {
|
|
266
|
+
setSelectedAsset(asset_2);
|
|
267
|
+
}, []);
|
|
268
|
+
const filteredAssets = searchQuery ? assets.filter((asset_3) => asset_3.fileName.toLowerCase().includes(searchQuery.toLowerCase()) || asset_3.title?.toLowerCase().includes(searchQuery.toLowerCase()) || asset_3.tags?.some((tag) => tag.toLowerCase().includes(searchQuery.toLowerCase()))) : assets;
|
|
269
|
+
return {
|
|
270
|
+
loading,
|
|
271
|
+
error,
|
|
272
|
+
assets: filteredAssets,
|
|
273
|
+
totalCount: assets.length,
|
|
274
|
+
selectedAsset,
|
|
275
|
+
selectAsset,
|
|
276
|
+
uploadFile,
|
|
277
|
+
deleteAsset,
|
|
278
|
+
updateAsset,
|
|
279
|
+
refreshAssets,
|
|
280
|
+
searchAssets,
|
|
281
|
+
storagePath,
|
|
282
|
+
collectionPath
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function getImageDimensions(file) {
|
|
286
|
+
return new Promise((resolve, reject) => {
|
|
287
|
+
const img = new Image();
|
|
288
|
+
img.onload = () => {
|
|
289
|
+
resolve({
|
|
290
|
+
width: img.width,
|
|
291
|
+
height: img.height
|
|
292
|
+
});
|
|
293
|
+
URL.revokeObjectURL(img.src);
|
|
294
|
+
};
|
|
295
|
+
img.onerror = reject;
|
|
296
|
+
img.src = URL.createObjectURL(file);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
async function generateThumbnail(file, maxWidth, maxHeight, quality) {
|
|
300
|
+
return new Promise((resolve, reject) => {
|
|
301
|
+
new Compressor(file, {
|
|
302
|
+
quality,
|
|
303
|
+
maxWidth,
|
|
304
|
+
maxHeight,
|
|
305
|
+
mimeType: "image/jpeg",
|
|
306
|
+
success: (result) => {
|
|
307
|
+
resolve(result);
|
|
308
|
+
},
|
|
309
|
+
error: reject
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
function MediaAssetCard(t0) {
|
|
314
|
+
const $ = reactCompilerRuntime.c(53);
|
|
315
|
+
const {
|
|
316
|
+
asset,
|
|
317
|
+
viewMode,
|
|
318
|
+
onClick,
|
|
319
|
+
selected,
|
|
320
|
+
thumbnailSize: t1
|
|
321
|
+
} = t0;
|
|
322
|
+
const thumbnailSize = t1 === void 0 ? "small" : t1;
|
|
323
|
+
let t2;
|
|
324
|
+
if ($[0] !== asset.mimeType) {
|
|
325
|
+
t2 = asset.mimeType.startsWith("image/");
|
|
326
|
+
$[0] = asset.mimeType;
|
|
327
|
+
$[1] = t2;
|
|
328
|
+
} else {
|
|
329
|
+
t2 = $[1];
|
|
330
|
+
}
|
|
331
|
+
const isImage = t2;
|
|
332
|
+
const isVideo = asset.mimeType.startsWith("video/");
|
|
333
|
+
const isAudio = asset.mimeType.startsWith("audio/");
|
|
334
|
+
const FileIcon = isImage ? ui.ImageIcon : isVideo ? ui.VideoLibraryIcon : isAudio ? ui.AudiotrackIcon : ui.DescriptionIcon;
|
|
335
|
+
const formatSize = _temp;
|
|
336
|
+
const imageUrl = asset.thumbnails?.[thumbnailSize] ?? asset.downloadURL;
|
|
337
|
+
let t3;
|
|
338
|
+
if ($[2] !== FileIcon || $[3] !== asset.altText || $[4] !== asset.fileName || $[5] !== imageUrl || $[6] !== isImage) {
|
|
339
|
+
t3 = isImage && imageUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: imageUrl, alt: asset.altText || asset.fileName, className: "w-full h-full object-cover transition-transform duration-200 group-hover:scale-105", loading: "lazy" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center bg-surface-100 dark:bg-surface-800", children: /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { size: "large", className: "text-surface-400 dark:text-surface-500" }) });
|
|
340
|
+
$[2] = FileIcon;
|
|
341
|
+
$[3] = asset.altText;
|
|
342
|
+
$[4] = asset.fileName;
|
|
343
|
+
$[5] = imageUrl;
|
|
344
|
+
$[6] = isImage;
|
|
345
|
+
$[7] = t3;
|
|
346
|
+
} else {
|
|
347
|
+
t3 = $[7];
|
|
348
|
+
}
|
|
349
|
+
const thumbnail = t3;
|
|
350
|
+
if (viewMode === "list") {
|
|
351
|
+
const t42 = selected && "ring-2 ring-primary bg-primary/5";
|
|
352
|
+
let t52;
|
|
353
|
+
if ($[8] !== t42) {
|
|
354
|
+
t52 = ui.cls("p-3 cursor-pointer flex items-center gap-3 rounded-lg", "hover:bg-surface-100 dark:hover:bg-surface-800", "transition-colors duration-150", `border ${ui.defaultBorderMixin}`, t42);
|
|
355
|
+
$[8] = t42;
|
|
356
|
+
$[9] = t52;
|
|
357
|
+
} else {
|
|
358
|
+
t52 = $[9];
|
|
359
|
+
}
|
|
360
|
+
let t62;
|
|
361
|
+
if ($[10] !== thumbnail) {
|
|
362
|
+
t62 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-md overflow-hidden flex-shrink-0 bg-surface-100 dark:bg-surface-800", children: thumbnail });
|
|
363
|
+
$[10] = thumbnail;
|
|
364
|
+
$[11] = t62;
|
|
365
|
+
} else {
|
|
366
|
+
t62 = $[11];
|
|
367
|
+
}
|
|
368
|
+
const t72 = asset.title || asset.fileName;
|
|
369
|
+
let t82;
|
|
370
|
+
if ($[12] !== t72) {
|
|
371
|
+
t82 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", className: "font-medium truncate text-surface-900 dark:text-white", children: t72 });
|
|
372
|
+
$[12] = t72;
|
|
373
|
+
$[13] = t82;
|
|
374
|
+
} else {
|
|
375
|
+
t82 = $[13];
|
|
376
|
+
}
|
|
377
|
+
const t92 = formatSize(asset.size);
|
|
378
|
+
let t102;
|
|
379
|
+
if ($[14] !== asset.mimeType) {
|
|
380
|
+
t102 = asset.mimeType.split("/")[1]?.toUpperCase();
|
|
381
|
+
$[14] = asset.mimeType;
|
|
382
|
+
$[15] = t102;
|
|
383
|
+
} else {
|
|
384
|
+
t102 = $[15];
|
|
385
|
+
}
|
|
386
|
+
let t112;
|
|
387
|
+
if ($[16] !== t102 || $[17] !== t92) {
|
|
388
|
+
t112 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Typography, { variant: "caption", color: "secondary", children: [
|
|
389
|
+
t92,
|
|
390
|
+
" • ",
|
|
391
|
+
t102
|
|
392
|
+
] });
|
|
393
|
+
$[16] = t102;
|
|
394
|
+
$[17] = t92;
|
|
395
|
+
$[18] = t112;
|
|
396
|
+
} else {
|
|
397
|
+
t112 = $[18];
|
|
398
|
+
}
|
|
399
|
+
let t122;
|
|
400
|
+
if ($[19] !== t112 || $[20] !== t82) {
|
|
401
|
+
t122 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
402
|
+
t82,
|
|
403
|
+
t112
|
|
404
|
+
] });
|
|
405
|
+
$[19] = t112;
|
|
406
|
+
$[20] = t82;
|
|
407
|
+
$[21] = t122;
|
|
408
|
+
} else {
|
|
409
|
+
t122 = $[21];
|
|
410
|
+
}
|
|
411
|
+
let t132;
|
|
412
|
+
if ($[22] !== selected) {
|
|
413
|
+
t132 = selected && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 rounded-full bg-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest", className: "text-white" }) });
|
|
414
|
+
$[22] = selected;
|
|
415
|
+
$[23] = t132;
|
|
416
|
+
} else {
|
|
417
|
+
t132 = $[23];
|
|
418
|
+
}
|
|
419
|
+
let t142;
|
|
420
|
+
if ($[24] !== onClick || $[25] !== t122 || $[26] !== t132 || $[27] !== t52 || $[28] !== t62) {
|
|
421
|
+
t142 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: t52, onClick, children: [
|
|
422
|
+
t62,
|
|
423
|
+
t122,
|
|
424
|
+
t132
|
|
425
|
+
] });
|
|
426
|
+
$[24] = onClick;
|
|
427
|
+
$[25] = t122;
|
|
428
|
+
$[26] = t132;
|
|
429
|
+
$[27] = t52;
|
|
430
|
+
$[28] = t62;
|
|
431
|
+
$[29] = t142;
|
|
432
|
+
} else {
|
|
433
|
+
t142 = $[29];
|
|
434
|
+
}
|
|
435
|
+
return t142;
|
|
436
|
+
}
|
|
437
|
+
const t4 = selected && "ring-2 ring-primary";
|
|
438
|
+
let t5;
|
|
439
|
+
if ($[30] !== t4) {
|
|
440
|
+
t5 = ui.cls("cursor-pointer overflow-hidden group relative", "transition-all duration-200", "hover:shadow-lg hover:-translate-y-0.5", t4);
|
|
441
|
+
$[30] = t4;
|
|
442
|
+
$[31] = t5;
|
|
443
|
+
} else {
|
|
444
|
+
t5 = $[31];
|
|
445
|
+
}
|
|
446
|
+
let t6;
|
|
447
|
+
if ($[32] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
448
|
+
t6 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.cls("absolute inset-0 bg-black/0 group-hover:bg-black/20", "transition-colors duration-200") });
|
|
449
|
+
$[32] = t6;
|
|
450
|
+
} else {
|
|
451
|
+
t6 = $[32];
|
|
452
|
+
}
|
|
453
|
+
let t7;
|
|
454
|
+
if ($[33] !== selected) {
|
|
455
|
+
t7 = selected && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-primary flex items-center justify-center shadow-md", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest", className: "text-white" }) });
|
|
456
|
+
$[33] = selected;
|
|
457
|
+
$[34] = t7;
|
|
458
|
+
} else {
|
|
459
|
+
t7 = $[34];
|
|
460
|
+
}
|
|
461
|
+
let t8;
|
|
462
|
+
if ($[35] !== t7 || $[36] !== thumbnail) {
|
|
463
|
+
t8 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aspect-square relative overflow-hidden bg-surface-100 dark:bg-surface-800", children: [
|
|
464
|
+
thumbnail,
|
|
465
|
+
t6,
|
|
466
|
+
t7
|
|
467
|
+
] });
|
|
468
|
+
$[35] = t7;
|
|
469
|
+
$[36] = thumbnail;
|
|
470
|
+
$[37] = t8;
|
|
471
|
+
} else {
|
|
472
|
+
t8 = $[37];
|
|
473
|
+
}
|
|
474
|
+
const t9 = asset.title || asset.fileName;
|
|
475
|
+
let t10;
|
|
476
|
+
if ($[38] !== t9) {
|
|
477
|
+
t10 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", className: "font-medium truncate text-surface-900 dark:text-white", children: t9 });
|
|
478
|
+
$[38] = t9;
|
|
479
|
+
$[39] = t10;
|
|
480
|
+
} else {
|
|
481
|
+
t10 = $[39];
|
|
482
|
+
}
|
|
483
|
+
const t11 = formatSize(asset.size);
|
|
484
|
+
let t12;
|
|
485
|
+
if ($[40] !== asset.mimeType) {
|
|
486
|
+
t12 = asset.mimeType.split("/")[1]?.toUpperCase();
|
|
487
|
+
$[40] = asset.mimeType;
|
|
488
|
+
$[41] = t12;
|
|
489
|
+
} else {
|
|
490
|
+
t12 = $[41];
|
|
491
|
+
}
|
|
492
|
+
let t13;
|
|
493
|
+
if ($[42] !== t11 || $[43] !== t12) {
|
|
494
|
+
t13 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Typography, { variant: "caption", color: "secondary", className: "truncate block mt-0.5", children: [
|
|
495
|
+
t11,
|
|
496
|
+
" • ",
|
|
497
|
+
t12
|
|
498
|
+
] });
|
|
499
|
+
$[42] = t11;
|
|
500
|
+
$[43] = t12;
|
|
501
|
+
$[44] = t13;
|
|
502
|
+
} else {
|
|
503
|
+
t13 = $[44];
|
|
504
|
+
}
|
|
505
|
+
let t14;
|
|
506
|
+
if ($[45] !== t10 || $[46] !== t13) {
|
|
507
|
+
t14 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3", children: [
|
|
508
|
+
t10,
|
|
509
|
+
t13
|
|
510
|
+
] });
|
|
511
|
+
$[45] = t10;
|
|
512
|
+
$[46] = t13;
|
|
513
|
+
$[47] = t14;
|
|
514
|
+
} else {
|
|
515
|
+
t14 = $[47];
|
|
516
|
+
}
|
|
517
|
+
let t15;
|
|
518
|
+
if ($[48] !== onClick || $[49] !== t14 || $[50] !== t5 || $[51] !== t8) {
|
|
519
|
+
t15 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Card, { className: t5, onClick, children: [
|
|
520
|
+
t8,
|
|
521
|
+
t14
|
|
522
|
+
] });
|
|
523
|
+
$[48] = onClick;
|
|
524
|
+
$[49] = t14;
|
|
525
|
+
$[50] = t5;
|
|
526
|
+
$[51] = t8;
|
|
527
|
+
$[52] = t15;
|
|
528
|
+
} else {
|
|
529
|
+
t15 = $[52];
|
|
530
|
+
}
|
|
531
|
+
return t15;
|
|
532
|
+
}
|
|
533
|
+
function _temp(bytes) {
|
|
534
|
+
if (bytes < 1024) {
|
|
535
|
+
return `${bytes} B`;
|
|
536
|
+
}
|
|
537
|
+
if (bytes < 1048576) {
|
|
538
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
539
|
+
}
|
|
540
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
541
|
+
}
|
|
542
|
+
function MediaAssetDetails({
|
|
543
|
+
asset,
|
|
544
|
+
onClose,
|
|
545
|
+
onUpdate,
|
|
546
|
+
onDelete
|
|
547
|
+
}) {
|
|
548
|
+
const snackbarController = core.useSnackbarController();
|
|
549
|
+
const storageSource = core.useStorageSource();
|
|
550
|
+
const [saving, setSaving] = react.useState(false);
|
|
551
|
+
const [deleting, setDeleting] = react.useState(false);
|
|
552
|
+
const [deleteDialogOpen, setDeleteDialogOpen] = react.useState(false);
|
|
553
|
+
const [tagInput, setTagInput] = react.useState("");
|
|
554
|
+
const {
|
|
555
|
+
t
|
|
556
|
+
} = core.useTranslation();
|
|
557
|
+
const {
|
|
558
|
+
values,
|
|
559
|
+
setFieldValue,
|
|
560
|
+
dirty
|
|
561
|
+
} = formex.useCreateFormex({
|
|
562
|
+
initialValues: {
|
|
563
|
+
title: asset.title ?? "",
|
|
564
|
+
altText: asset.altText ?? "",
|
|
565
|
+
caption: asset.caption ?? "",
|
|
566
|
+
tags: asset.tags ?? []
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
const handleSave = react.useCallback(async () => {
|
|
570
|
+
setSaving(true);
|
|
571
|
+
try {
|
|
572
|
+
await onUpdate(asset.id, values);
|
|
573
|
+
snackbarController.open({
|
|
574
|
+
type: "success",
|
|
575
|
+
message: t("media_asset_updated")
|
|
576
|
+
});
|
|
577
|
+
} catch (error) {
|
|
578
|
+
snackbarController.open({
|
|
579
|
+
type: "error",
|
|
580
|
+
message: t("media_error_updating", {
|
|
581
|
+
message: error instanceof Error ? error.message : String(error)
|
|
582
|
+
})
|
|
583
|
+
});
|
|
584
|
+
} finally {
|
|
585
|
+
setSaving(false);
|
|
586
|
+
}
|
|
587
|
+
}, [asset.id, values, onUpdate, snackbarController]);
|
|
588
|
+
const handleDelete = react.useCallback(async () => {
|
|
589
|
+
setDeleting(true);
|
|
590
|
+
try {
|
|
591
|
+
await onDelete(asset.id);
|
|
592
|
+
snackbarController.open({
|
|
593
|
+
type: "success",
|
|
594
|
+
message: t("media_asset_deleted")
|
|
595
|
+
});
|
|
596
|
+
onClose();
|
|
597
|
+
} catch (error_0) {
|
|
598
|
+
snackbarController.open({
|
|
599
|
+
type: "error",
|
|
600
|
+
message: t("media_error_deleting", {
|
|
601
|
+
message: error_0 instanceof Error ? error_0.message : String(error_0)
|
|
602
|
+
})
|
|
603
|
+
});
|
|
604
|
+
} finally {
|
|
605
|
+
setDeleting(false);
|
|
606
|
+
setDeleteDialogOpen(false);
|
|
607
|
+
}
|
|
608
|
+
}, [asset.id, onDelete, snackbarController, onClose]);
|
|
609
|
+
const handleDownload = react.useCallback(async () => {
|
|
610
|
+
try {
|
|
611
|
+
const downloadConfig = await storageSource.getDownloadURL(asset.storagePath, asset.bucket);
|
|
612
|
+
if (downloadConfig.url) {
|
|
613
|
+
window.open(downloadConfig.url, "_blank");
|
|
614
|
+
}
|
|
615
|
+
} catch (error_1) {
|
|
616
|
+
snackbarController.open({
|
|
617
|
+
type: "error",
|
|
618
|
+
message: t("media_error_getting_url")
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
}, [asset, storageSource, snackbarController]);
|
|
622
|
+
const handleAddTag = react.useCallback(() => {
|
|
623
|
+
const tag = tagInput.trim();
|
|
624
|
+
if (tag && !values.tags?.includes(tag)) {
|
|
625
|
+
setFieldValue("tags", [...values.tags ?? [], tag]);
|
|
626
|
+
setTagInput("");
|
|
627
|
+
}
|
|
628
|
+
}, [tagInput, values.tags, setFieldValue]);
|
|
629
|
+
const handleRemoveTag = react.useCallback((tagToRemove) => {
|
|
630
|
+
setFieldValue("tags", values.tags?.filter((t_0) => t_0 !== tagToRemove) ?? []);
|
|
631
|
+
}, [values.tags, setFieldValue]);
|
|
632
|
+
const formatSize = (bytes) => {
|
|
633
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
634
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
635
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
636
|
+
};
|
|
637
|
+
const formatDate = (date) => {
|
|
638
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
639
|
+
year: "numeric",
|
|
640
|
+
month: "short",
|
|
641
|
+
day: "numeric"
|
|
642
|
+
}).format(date);
|
|
643
|
+
};
|
|
644
|
+
const isImage = asset.mimeType.startsWith("image/");
|
|
645
|
+
const isVideo = asset.mimeType.startsWith("video/");
|
|
646
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
647
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("fixed inset-y-0 right-0 w-full sm:w-96 lg:w-[480px]", "bg-surface-50 dark:bg-surface-900", "border-l border-surface-accent-200 dark:border-surface-accent-700", "shadow-xl z-50", "flex flex-col", "animate-slide-in-right"), children: [
|
|
648
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b border-surface-accent-200 dark:border-surface-accent-700", children: [
|
|
649
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle1", className: "font-medium truncate flex-1 mr-2", children: asset.title || asset.fileName }),
|
|
650
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
651
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: handleDownload, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DownloadIcon, { size: "small" }) }),
|
|
652
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: () => setDeleteDialogOpen(true), className: "text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20", children: /* @__PURE__ */ jsxRuntime.jsx(ui.DeleteIcon, { size: "small" }) }),
|
|
653
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, { size: "small" }) })
|
|
654
|
+
] })
|
|
655
|
+
] }),
|
|
656
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 bg-surface-accent-100 dark:bg-surface-accent-800 flex items-center justify-center min-h-48 max-h-64", children: isImage && asset.downloadURL ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: asset.downloadURL, alt: asset.altText || asset.fileName, className: "max-w-full max-h-full object-contain" }) : isVideo && asset.downloadURL ? /* @__PURE__ */ jsxRuntime.jsx("video", { src: asset.downloadURL, className: "max-w-full max-h-full", controls: true }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-surface-accent-400", children: t("media_preview_not_available") }) }),
|
|
657
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-auto p-4 space-y-4", children: [
|
|
658
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
659
|
+
asset.dimensions && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
660
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500", children: t("media_dimensions") }),
|
|
661
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Typography, { variant: "body2", children: [
|
|
662
|
+
asset.dimensions.width,
|
|
663
|
+
" × ",
|
|
664
|
+
asset.dimensions.height,
|
|
665
|
+
" px"
|
|
666
|
+
] })
|
|
667
|
+
] }),
|
|
668
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
669
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500", children: t("media_size") }),
|
|
670
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", children: formatSize(asset.size) })
|
|
671
|
+
] }),
|
|
672
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
673
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500", children: t("media_type") }),
|
|
674
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", children: asset.mimeType })
|
|
675
|
+
] }),
|
|
676
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
677
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500", children: t("media_created") }),
|
|
678
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", children: formatDate(asset.createdAt) })
|
|
679
|
+
] })
|
|
680
|
+
] }),
|
|
681
|
+
/* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-surface-accent-200 dark:border-surface-accent-700" }),
|
|
682
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TextField, { label: t("media_file_name"), value: asset.fileName, disabled: true, size: "small" }),
|
|
683
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TextField, { label: t("media_title"), value: values.title ?? "", onChange: (e) => setFieldValue("title", e.target.value), size: "small" }),
|
|
684
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
685
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TextField, { label: t("media_alt_text"), value: values.altText ?? "", onChange: (e_0) => setFieldValue("altText", e_0.target.value), size: "small" }),
|
|
686
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500 mt-1", children: t("media_recommended_seo") })
|
|
687
|
+
] }),
|
|
688
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TextField, { label: t("media_caption"), value: values.caption ?? "", onChange: (e_1) => setFieldValue("caption", e_1.target.value), size: "small", multiline: true }),
|
|
689
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
690
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500 mb-1 block", children: t("media_tags") }),
|
|
691
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 mb-2", children: values.tags?.map((tag_0) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Chip, { size: "small", colorScheme: "blueLighter", onClick: () => handleRemoveTag(tag_0), children: [
|
|
692
|
+
tag_0,
|
|
693
|
+
" ×"
|
|
694
|
+
] }, tag_0)) }),
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
696
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TextField, { placeholder: t("media_add_tag"), value: tagInput, onChange: (e_2) => setTagInput(e_2.target.value), size: "small", className: "flex-1", onKeyDown: (e_3) => {
|
|
697
|
+
if (e_3.key === "Enter") {
|
|
698
|
+
e_3.preventDefault();
|
|
699
|
+
handleAddTag();
|
|
700
|
+
}
|
|
701
|
+
} }),
|
|
702
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", size: "small", onClick: handleAddTag, disabled: !tagInput.trim(), children: t("media_add") })
|
|
703
|
+
] })
|
|
704
|
+
] })
|
|
705
|
+
] }),
|
|
706
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 p-4 border-t border-surface-accent-200 dark:border-surface-accent-700", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "filled", onClick: handleSave, disabled: !dirty || saving, className: "w-full", children: saving ? /* @__PURE__ */ jsxRuntime.jsx(ui.CircularProgress, { size: "small" }) : t("media_save_changes") }) })
|
|
707
|
+
] }),
|
|
708
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Dialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
|
|
709
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { children: [
|
|
710
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle1", className: "font-medium mb-2", children: t("media_delete_asset") }),
|
|
711
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { className: "text-surface-accent-600 dark:text-surface-accent-400", children: t("media_delete_confirmation", {
|
|
712
|
+
name: asset.title || asset.fileName
|
|
713
|
+
}) })
|
|
714
|
+
] }),
|
|
715
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { children: [
|
|
716
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", onClick: () => setDeleteDialogOpen(false), disabled: deleting, children: t("cancel") }),
|
|
717
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "filled", color: "error", onClick: handleDelete, disabled: deleting, children: deleting ? /* @__PURE__ */ jsxRuntime.jsx(ui.CircularProgress, { size: "small" }) : t("delete") })
|
|
718
|
+
] })
|
|
719
|
+
] })
|
|
720
|
+
] });
|
|
721
|
+
}
|
|
722
|
+
function MediaUploadDialog({
|
|
723
|
+
open,
|
|
724
|
+
onClose,
|
|
725
|
+
onUpload,
|
|
726
|
+
maxFileSize = 52428800,
|
|
727
|
+
// 50MB default
|
|
728
|
+
acceptedMimeTypes
|
|
729
|
+
}) {
|
|
730
|
+
const [isDragging, setIsDragging] = react.useState(false);
|
|
731
|
+
const [uploading, setUploading] = react.useState(false);
|
|
732
|
+
const [error, setError] = react.useState(null);
|
|
733
|
+
const [selectedFiles, setSelectedFiles] = react.useState([]);
|
|
734
|
+
const {
|
|
735
|
+
t
|
|
736
|
+
} = core.useTranslation();
|
|
737
|
+
const validateFiles = react.useCallback((files) => {
|
|
738
|
+
const valid = [];
|
|
739
|
+
const errors = [];
|
|
740
|
+
for (const file of files) {
|
|
741
|
+
if (maxFileSize && file.size > maxFileSize) {
|
|
742
|
+
errors.push(t("media_file_too_large", {
|
|
743
|
+
name: file.name,
|
|
744
|
+
size: formatSize(maxFileSize)
|
|
745
|
+
}));
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
if (acceptedMimeTypes && !acceptedMimeTypes.some((type) => {
|
|
749
|
+
if (type.endsWith("/*")) {
|
|
750
|
+
return file.type.startsWith(type.slice(0, -1));
|
|
751
|
+
}
|
|
752
|
+
return file.type === type;
|
|
753
|
+
})) {
|
|
754
|
+
errors.push(t("media_file_type_not_allowed", {
|
|
755
|
+
name: file.name
|
|
756
|
+
}));
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
valid.push(file);
|
|
760
|
+
}
|
|
761
|
+
return {
|
|
762
|
+
valid,
|
|
763
|
+
errors
|
|
764
|
+
};
|
|
765
|
+
}, [maxFileSize, acceptedMimeTypes]);
|
|
766
|
+
const handleDragOver = react.useCallback((e) => {
|
|
767
|
+
e.preventDefault();
|
|
768
|
+
setIsDragging(true);
|
|
769
|
+
}, []);
|
|
770
|
+
const handleDragLeave = react.useCallback((e_0) => {
|
|
771
|
+
e_0.preventDefault();
|
|
772
|
+
setIsDragging(false);
|
|
773
|
+
}, []);
|
|
774
|
+
const handleDrop = react.useCallback((e_1) => {
|
|
775
|
+
e_1.preventDefault();
|
|
776
|
+
setIsDragging(false);
|
|
777
|
+
const files_0 = Array.from(e_1.dataTransfer.files);
|
|
778
|
+
const {
|
|
779
|
+
valid: valid_0,
|
|
780
|
+
errors: errors_0
|
|
781
|
+
} = validateFiles(files_0);
|
|
782
|
+
if (errors_0.length > 0) {
|
|
783
|
+
setError(errors_0.join("\n"));
|
|
784
|
+
} else {
|
|
785
|
+
setError(null);
|
|
786
|
+
}
|
|
787
|
+
setSelectedFiles((prev) => [...prev, ...valid_0]);
|
|
788
|
+
}, [validateFiles]);
|
|
789
|
+
const handleFileSelect = react.useCallback((e_2) => {
|
|
790
|
+
const files_1 = Array.from(e_2.target.files ?? []);
|
|
791
|
+
const {
|
|
792
|
+
valid: valid_1,
|
|
793
|
+
errors: errors_1
|
|
794
|
+
} = validateFiles(files_1);
|
|
795
|
+
if (errors_1.length > 0) {
|
|
796
|
+
setError(errors_1.join("\n"));
|
|
797
|
+
} else {
|
|
798
|
+
setError(null);
|
|
799
|
+
}
|
|
800
|
+
setSelectedFiles((prev_0) => [...prev_0, ...valid_1]);
|
|
801
|
+
}, [validateFiles]);
|
|
802
|
+
const handleRemoveFile = react.useCallback((index) => {
|
|
803
|
+
setSelectedFiles((prev_1) => prev_1.filter((_, i) => i !== index));
|
|
804
|
+
}, []);
|
|
805
|
+
const handleUpload = react.useCallback(async () => {
|
|
806
|
+
if (selectedFiles.length === 0) return;
|
|
807
|
+
setUploading(true);
|
|
808
|
+
setError(null);
|
|
809
|
+
try {
|
|
810
|
+
await onUpload(selectedFiles);
|
|
811
|
+
setSelectedFiles([]);
|
|
812
|
+
onClose();
|
|
813
|
+
} catch (err) {
|
|
814
|
+
setError(err instanceof Error ? err.message : t("media_upload_failed"));
|
|
815
|
+
} finally {
|
|
816
|
+
setUploading(false);
|
|
817
|
+
}
|
|
818
|
+
}, [selectedFiles, onUpload, onClose]);
|
|
819
|
+
const handleClose = react.useCallback(() => {
|
|
820
|
+
if (!uploading) {
|
|
821
|
+
setSelectedFiles([]);
|
|
822
|
+
setError(null);
|
|
823
|
+
onClose();
|
|
824
|
+
}
|
|
825
|
+
}, [uploading, onClose]);
|
|
826
|
+
const formatSize = (bytes) => {
|
|
827
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
828
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
829
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
830
|
+
};
|
|
831
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Dialog, { open, onOpenChange: (open_0) => !open_0 && handleClose(), maxWidth: "md", children: [
|
|
832
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { className: "p-0", children: [
|
|
833
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 border-b border-surface-accent-200 dark:border-surface-accent-700", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "h6", children: t("media_upload_files") }) }),
|
|
834
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
835
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("border-2 border-dashed rounded-lg p-8", "flex flex-col items-center justify-center gap-4", "transition-colors duration-150", isDragging ? "border-primary bg-primary/5" : "border-surface-accent-300 dark:border-surface-accent-600", "hover:border-primary hover:bg-primary/5", "cursor-pointer"), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: () => document.getElementById("file-upload-input")?.click(), children: [
|
|
836
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.CloudUploadIcon, { size: "large", className: ui.cls(isDragging ? "text-primary" : "text-surface-accent-400") }),
|
|
837
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
838
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body1", className: "font-medium", children: t("media_drop_files") }),
|
|
839
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500", children: t("media_max_file_size", {
|
|
840
|
+
size: formatSize(maxFileSize)
|
|
841
|
+
}) })
|
|
842
|
+
] }),
|
|
843
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { id: "file-upload-input", type: "file", multiple: true, accept: acceptedMimeTypes?.join(","), onChange: handleFileSelect, className: "hidden" })
|
|
844
|
+
] }),
|
|
845
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-red-500 mt-2 block whitespace-pre-line", children: error }),
|
|
846
|
+
selectedFiles.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-2", children: [
|
|
847
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500", children: t("media_selected_files_count", {
|
|
848
|
+
count: selectedFiles.length.toString()
|
|
849
|
+
}) }),
|
|
850
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-40 overflow-auto space-y-1", children: selectedFiles.map((file_0, index_0) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("flex items-center justify-between p-2 rounded", "bg-surface-accent-50 dark:bg-surface-accent-800"), children: [
|
|
851
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 mr-2", children: [
|
|
852
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", className: "truncate", children: file_0.name }),
|
|
853
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-500", children: formatSize(file_0.size) })
|
|
854
|
+
] }),
|
|
855
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", size: "small", onClick: (e_3) => {
|
|
856
|
+
e_3.stopPropagation();
|
|
857
|
+
handleRemoveFile(index_0);
|
|
858
|
+
}, disabled: uploading, children: t("media_remove") })
|
|
859
|
+
] }, `${file_0.name}-${index_0}`)) })
|
|
860
|
+
] })
|
|
861
|
+
] })
|
|
862
|
+
] }),
|
|
863
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { children: [
|
|
864
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", onClick: handleClose, disabled: uploading, children: t("cancel") }),
|
|
865
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "filled", onClick: handleUpload, disabled: selectedFiles.length === 0 || uploading, children: uploading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
866
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.CircularProgress, { size: "smallest" }),
|
|
867
|
+
t("media_uploading")
|
|
868
|
+
] }) : `${t("media_upload")} ${selectedFiles.length > 0 ? `(${selectedFiles.length})` : ""}` })
|
|
869
|
+
] })
|
|
870
|
+
] });
|
|
871
|
+
}
|
|
872
|
+
function MediaLibraryView(t0) {
|
|
873
|
+
const $ = reactCompilerRuntime.c(87);
|
|
874
|
+
const {
|
|
875
|
+
maxFileSize,
|
|
876
|
+
acceptedMimeTypes
|
|
877
|
+
} = t0;
|
|
878
|
+
const controller = useMediaManager();
|
|
879
|
+
const [uploadDialogOpen, setUploadDialogOpen] = react.useState(false);
|
|
880
|
+
const [viewMode, setViewMode] = react.useState("grid");
|
|
881
|
+
react.useRef(null);
|
|
882
|
+
const {
|
|
883
|
+
t
|
|
884
|
+
} = core.useTranslation();
|
|
885
|
+
let t1;
|
|
886
|
+
if ($[0] !== controller) {
|
|
887
|
+
t1 = (query) => {
|
|
888
|
+
controller.searchAssets(query ?? "");
|
|
889
|
+
};
|
|
890
|
+
$[0] = controller;
|
|
891
|
+
$[1] = t1;
|
|
892
|
+
} else {
|
|
893
|
+
t1 = $[1];
|
|
894
|
+
}
|
|
895
|
+
const handleSearch = t1;
|
|
896
|
+
let t2;
|
|
897
|
+
if ($[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
898
|
+
t2 = () => {
|
|
899
|
+
setUploadDialogOpen(true);
|
|
900
|
+
};
|
|
901
|
+
$[2] = t2;
|
|
902
|
+
} else {
|
|
903
|
+
t2 = $[2];
|
|
904
|
+
}
|
|
905
|
+
const handleUploadClick = t2;
|
|
906
|
+
let t3;
|
|
907
|
+
if ($[3] !== controller) {
|
|
908
|
+
t3 = async (files) => {
|
|
909
|
+
for (const file of files) {
|
|
910
|
+
await controller.uploadFile(file);
|
|
911
|
+
}
|
|
912
|
+
setUploadDialogOpen(false);
|
|
913
|
+
};
|
|
914
|
+
$[3] = controller;
|
|
915
|
+
$[4] = t3;
|
|
916
|
+
} else {
|
|
917
|
+
t3 = $[4];
|
|
918
|
+
}
|
|
919
|
+
const handleFileSelect = t3;
|
|
920
|
+
let t4;
|
|
921
|
+
if ($[5] !== controller) {
|
|
922
|
+
t4 = () => {
|
|
923
|
+
controller.refreshAssets();
|
|
924
|
+
};
|
|
925
|
+
$[5] = controller;
|
|
926
|
+
$[6] = t4;
|
|
927
|
+
} else {
|
|
928
|
+
t4 = $[6];
|
|
929
|
+
}
|
|
930
|
+
const handleRefresh = t4;
|
|
931
|
+
let t5;
|
|
932
|
+
if ($[7] !== t) {
|
|
933
|
+
t5 = t("media_library");
|
|
934
|
+
$[7] = t;
|
|
935
|
+
$[8] = t5;
|
|
936
|
+
} else {
|
|
937
|
+
t5 = $[8];
|
|
938
|
+
}
|
|
939
|
+
let t6;
|
|
940
|
+
if ($[9] !== t5) {
|
|
941
|
+
t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "h5", className: "font-semibold", children: t5 });
|
|
942
|
+
$[9] = t5;
|
|
943
|
+
$[10] = t6;
|
|
944
|
+
} else {
|
|
945
|
+
t6 = $[10];
|
|
946
|
+
}
|
|
947
|
+
let t7;
|
|
948
|
+
if ($[11] !== controller.totalCount || $[12] !== t) {
|
|
949
|
+
t7 = controller.totalCount !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "bg-surface-accent-100 dark:bg-surface-accent-800 px-2 py-0.5 rounded-full", children: t("media_assets_count", {
|
|
950
|
+
count: controller.totalCount.toString()
|
|
951
|
+
}) });
|
|
952
|
+
$[11] = controller.totalCount;
|
|
953
|
+
$[12] = t;
|
|
954
|
+
$[13] = t7;
|
|
955
|
+
} else {
|
|
956
|
+
t7 = $[13];
|
|
957
|
+
}
|
|
958
|
+
let t8;
|
|
959
|
+
if ($[14] !== t6 || $[15] !== t7) {
|
|
960
|
+
t8 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
961
|
+
t6,
|
|
962
|
+
t7
|
|
963
|
+
] });
|
|
964
|
+
$[14] = t6;
|
|
965
|
+
$[15] = t7;
|
|
966
|
+
$[16] = t8;
|
|
967
|
+
} else {
|
|
968
|
+
t8 = $[16];
|
|
969
|
+
}
|
|
970
|
+
let t9;
|
|
971
|
+
if ($[17] !== t) {
|
|
972
|
+
t9 = t("media_search_assets");
|
|
973
|
+
$[17] = t;
|
|
974
|
+
$[18] = t9;
|
|
975
|
+
} else {
|
|
976
|
+
t9 = $[18];
|
|
977
|
+
}
|
|
978
|
+
let t10;
|
|
979
|
+
if ($[19] !== handleSearch || $[20] !== t9) {
|
|
980
|
+
t10 = /* @__PURE__ */ jsxRuntime.jsx(ui.SearchBar, { onTextSearch: handleSearch, placeholder: t9, className: "flex-1 sm:w-64" });
|
|
981
|
+
$[19] = handleSearch;
|
|
982
|
+
$[20] = t9;
|
|
983
|
+
$[21] = t10;
|
|
984
|
+
} else {
|
|
985
|
+
t10 = $[21];
|
|
986
|
+
}
|
|
987
|
+
let t11;
|
|
988
|
+
if ($[22] !== t) {
|
|
989
|
+
t11 = t("media_grid_view");
|
|
990
|
+
$[22] = t;
|
|
991
|
+
$[23] = t11;
|
|
992
|
+
} else {
|
|
993
|
+
t11 = $[23];
|
|
994
|
+
}
|
|
995
|
+
let t12;
|
|
996
|
+
if ($[24] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
997
|
+
t12 = () => setViewMode("grid");
|
|
998
|
+
$[24] = t12;
|
|
999
|
+
} else {
|
|
1000
|
+
t12 = $[24];
|
|
1001
|
+
}
|
|
1002
|
+
const t13 = viewMode === "grid" && "bg-surface-accent-100 dark:bg-surface-accent-800";
|
|
1003
|
+
let t14;
|
|
1004
|
+
if ($[25] !== t13) {
|
|
1005
|
+
t14 = ui.cls(t13);
|
|
1006
|
+
$[25] = t13;
|
|
1007
|
+
$[26] = t14;
|
|
1008
|
+
} else {
|
|
1009
|
+
t14 = $[26];
|
|
1010
|
+
}
|
|
1011
|
+
let t15;
|
|
1012
|
+
if ($[27] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1013
|
+
t15 = /* @__PURE__ */ jsxRuntime.jsx(ui.AppsIcon, { size: "small" });
|
|
1014
|
+
$[27] = t15;
|
|
1015
|
+
} else {
|
|
1016
|
+
t15 = $[27];
|
|
1017
|
+
}
|
|
1018
|
+
let t16;
|
|
1019
|
+
if ($[28] !== t14) {
|
|
1020
|
+
t16 = /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: t12, className: t14, children: t15 });
|
|
1021
|
+
$[28] = t14;
|
|
1022
|
+
$[29] = t16;
|
|
1023
|
+
} else {
|
|
1024
|
+
t16 = $[29];
|
|
1025
|
+
}
|
|
1026
|
+
let t17;
|
|
1027
|
+
if ($[30] !== t11 || $[31] !== t16) {
|
|
1028
|
+
t17 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: t11, children: t16 });
|
|
1029
|
+
$[30] = t11;
|
|
1030
|
+
$[31] = t16;
|
|
1031
|
+
$[32] = t17;
|
|
1032
|
+
} else {
|
|
1033
|
+
t17 = $[32];
|
|
1034
|
+
}
|
|
1035
|
+
let t18;
|
|
1036
|
+
if ($[33] !== t) {
|
|
1037
|
+
t18 = t("media_list_view");
|
|
1038
|
+
$[33] = t;
|
|
1039
|
+
$[34] = t18;
|
|
1040
|
+
} else {
|
|
1041
|
+
t18 = $[34];
|
|
1042
|
+
}
|
|
1043
|
+
let t19;
|
|
1044
|
+
if ($[35] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1045
|
+
t19 = () => setViewMode("list");
|
|
1046
|
+
$[35] = t19;
|
|
1047
|
+
} else {
|
|
1048
|
+
t19 = $[35];
|
|
1049
|
+
}
|
|
1050
|
+
const t20 = viewMode === "list" && "bg-surface-accent-100 dark:bg-surface-accent-800";
|
|
1051
|
+
let t21;
|
|
1052
|
+
if ($[36] !== t20) {
|
|
1053
|
+
t21 = ui.cls(t20);
|
|
1054
|
+
$[36] = t20;
|
|
1055
|
+
$[37] = t21;
|
|
1056
|
+
} else {
|
|
1057
|
+
t21 = $[37];
|
|
1058
|
+
}
|
|
1059
|
+
let t22;
|
|
1060
|
+
if ($[38] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1061
|
+
t22 = /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { iconKey: "list", size: "small" });
|
|
1062
|
+
$[38] = t22;
|
|
1063
|
+
} else {
|
|
1064
|
+
t22 = $[38];
|
|
1065
|
+
}
|
|
1066
|
+
let t23;
|
|
1067
|
+
if ($[39] !== t21) {
|
|
1068
|
+
t23 = /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: t19, className: t21, children: t22 });
|
|
1069
|
+
$[39] = t21;
|
|
1070
|
+
$[40] = t23;
|
|
1071
|
+
} else {
|
|
1072
|
+
t23 = $[40];
|
|
1073
|
+
}
|
|
1074
|
+
let t24;
|
|
1075
|
+
if ($[41] !== t18 || $[42] !== t23) {
|
|
1076
|
+
t24 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: t18, children: t23 });
|
|
1077
|
+
$[41] = t18;
|
|
1078
|
+
$[42] = t23;
|
|
1079
|
+
$[43] = t24;
|
|
1080
|
+
} else {
|
|
1081
|
+
t24 = $[43];
|
|
1082
|
+
}
|
|
1083
|
+
let t25;
|
|
1084
|
+
if ($[44] !== t17 || $[45] !== t24) {
|
|
1085
|
+
t25 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 border-l border-surface-accent-200 dark:border-surface-accent-700 pl-2 ml-2", children: [
|
|
1086
|
+
t17,
|
|
1087
|
+
t24
|
|
1088
|
+
] });
|
|
1089
|
+
$[44] = t17;
|
|
1090
|
+
$[45] = t24;
|
|
1091
|
+
$[46] = t25;
|
|
1092
|
+
} else {
|
|
1093
|
+
t25 = $[46];
|
|
1094
|
+
}
|
|
1095
|
+
let t26;
|
|
1096
|
+
if ($[47] !== t) {
|
|
1097
|
+
t26 = t("media_refresh");
|
|
1098
|
+
$[47] = t;
|
|
1099
|
+
$[48] = t26;
|
|
1100
|
+
} else {
|
|
1101
|
+
t26 = $[48];
|
|
1102
|
+
}
|
|
1103
|
+
let t27;
|
|
1104
|
+
if ($[49] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1105
|
+
t27 = /* @__PURE__ */ jsxRuntime.jsx(ui.RefreshIcon, { size: "small" });
|
|
1106
|
+
$[49] = t27;
|
|
1107
|
+
} else {
|
|
1108
|
+
t27 = $[49];
|
|
1109
|
+
}
|
|
1110
|
+
let t28;
|
|
1111
|
+
if ($[50] !== controller.loading || $[51] !== handleRefresh) {
|
|
1112
|
+
t28 = /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: handleRefresh, disabled: controller.loading, children: t27 });
|
|
1113
|
+
$[50] = controller.loading;
|
|
1114
|
+
$[51] = handleRefresh;
|
|
1115
|
+
$[52] = t28;
|
|
1116
|
+
} else {
|
|
1117
|
+
t28 = $[52];
|
|
1118
|
+
}
|
|
1119
|
+
let t29;
|
|
1120
|
+
if ($[53] !== t26 || $[54] !== t28) {
|
|
1121
|
+
t29 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: t26, children: t28 });
|
|
1122
|
+
$[53] = t26;
|
|
1123
|
+
$[54] = t28;
|
|
1124
|
+
$[55] = t29;
|
|
1125
|
+
} else {
|
|
1126
|
+
t29 = $[55];
|
|
1127
|
+
}
|
|
1128
|
+
let t30;
|
|
1129
|
+
if ($[56] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1130
|
+
t30 = /* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, { size: "small" });
|
|
1131
|
+
$[56] = t30;
|
|
1132
|
+
} else {
|
|
1133
|
+
t30 = $[56];
|
|
1134
|
+
}
|
|
1135
|
+
let t31;
|
|
1136
|
+
if ($[57] !== t) {
|
|
1137
|
+
t31 = t("media_upload");
|
|
1138
|
+
$[57] = t;
|
|
1139
|
+
$[58] = t31;
|
|
1140
|
+
} else {
|
|
1141
|
+
t31 = $[58];
|
|
1142
|
+
}
|
|
1143
|
+
let t32;
|
|
1144
|
+
if ($[59] !== t31) {
|
|
1145
|
+
t32 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "filled", onClick: handleUploadClick, children: [
|
|
1146
|
+
t30,
|
|
1147
|
+
t31
|
|
1148
|
+
] });
|
|
1149
|
+
$[59] = t31;
|
|
1150
|
+
$[60] = t32;
|
|
1151
|
+
} else {
|
|
1152
|
+
t32 = $[60];
|
|
1153
|
+
}
|
|
1154
|
+
let t33;
|
|
1155
|
+
if ($[61] !== t10 || $[62] !== t25 || $[63] !== t29 || $[64] !== t32) {
|
|
1156
|
+
t33 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 w-full sm:w-auto", children: [
|
|
1157
|
+
t10,
|
|
1158
|
+
t25,
|
|
1159
|
+
t29,
|
|
1160
|
+
t32
|
|
1161
|
+
] });
|
|
1162
|
+
$[61] = t10;
|
|
1163
|
+
$[62] = t25;
|
|
1164
|
+
$[63] = t29;
|
|
1165
|
+
$[64] = t32;
|
|
1166
|
+
$[65] = t33;
|
|
1167
|
+
} else {
|
|
1168
|
+
t33 = $[65];
|
|
1169
|
+
}
|
|
1170
|
+
let t34;
|
|
1171
|
+
if ($[66] !== t33 || $[67] !== t8) {
|
|
1172
|
+
t34 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 border-b border-surface-accent-200 dark:border-surface-accent-700 bg-surface-50 dark:bg-surface-900", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { maxWidth: "6xl", className: "py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-4 items-start sm:items-center justify-between", children: [
|
|
1173
|
+
t8,
|
|
1174
|
+
t33
|
|
1175
|
+
] }) }) });
|
|
1176
|
+
$[66] = t33;
|
|
1177
|
+
$[67] = t8;
|
|
1178
|
+
$[68] = t34;
|
|
1179
|
+
} else {
|
|
1180
|
+
t34 = $[68];
|
|
1181
|
+
}
|
|
1182
|
+
let t35;
|
|
1183
|
+
if ($[69] !== controller || $[70] !== handleRefresh || $[71] !== t || $[72] !== viewMode) {
|
|
1184
|
+
t35 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { maxWidth: "6xl", className: "py-6", children: controller.loading && controller.assets.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-64", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CircularProgress, {}) }) : controller.error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center h-64 gap-4", children: [
|
|
1185
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { className: "text-red-500", children: t("media_error_loading", {
|
|
1186
|
+
message: controller.error.message
|
|
1187
|
+
}) }),
|
|
1188
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { onClick: handleRefresh, children: t("media_try_again") })
|
|
1189
|
+
] }) : controller.assets.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center h-64 gap-4", children: [
|
|
1190
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { className: "text-surface-accent-500", children: t("media_no_assets") }),
|
|
1191
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { onClick: handleUploadClick, children: [
|
|
1192
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, { size: "small" }),
|
|
1193
|
+
t("media_upload_first_file")
|
|
1194
|
+
] })
|
|
1195
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.cls(viewMode === "grid" ? "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4" : "flex flex-col gap-2"), children: controller.assets.map((asset) => /* @__PURE__ */ jsxRuntime.jsx(MediaAssetCard, { asset, viewMode, onClick: () => controller.selectAsset(asset), selected: controller.selectedAsset?.id === asset.id }, asset.id)) }) }) });
|
|
1196
|
+
$[69] = controller;
|
|
1197
|
+
$[70] = handleRefresh;
|
|
1198
|
+
$[71] = t;
|
|
1199
|
+
$[72] = viewMode;
|
|
1200
|
+
$[73] = t35;
|
|
1201
|
+
} else {
|
|
1202
|
+
t35 = $[73];
|
|
1203
|
+
}
|
|
1204
|
+
let t36;
|
|
1205
|
+
if ($[74] !== controller) {
|
|
1206
|
+
t36 = controller.selectedAsset && /* @__PURE__ */ jsxRuntime.jsx(MediaAssetDetails, { asset: controller.selectedAsset, onClose: () => controller.selectAsset(void 0), onUpdate: controller.updateAsset, onDelete: controller.deleteAsset });
|
|
1207
|
+
$[74] = controller;
|
|
1208
|
+
$[75] = t36;
|
|
1209
|
+
} else {
|
|
1210
|
+
t36 = $[75];
|
|
1211
|
+
}
|
|
1212
|
+
let t37;
|
|
1213
|
+
if ($[76] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1214
|
+
t37 = () => setUploadDialogOpen(false);
|
|
1215
|
+
$[76] = t37;
|
|
1216
|
+
} else {
|
|
1217
|
+
t37 = $[76];
|
|
1218
|
+
}
|
|
1219
|
+
let t38;
|
|
1220
|
+
if ($[77] !== acceptedMimeTypes || $[78] !== handleFileSelect || $[79] !== maxFileSize || $[80] !== uploadDialogOpen) {
|
|
1221
|
+
t38 = /* @__PURE__ */ jsxRuntime.jsx(MediaUploadDialog, { open: uploadDialogOpen, onClose: t37, onUpload: handleFileSelect, maxFileSize, acceptedMimeTypes });
|
|
1222
|
+
$[77] = acceptedMimeTypes;
|
|
1223
|
+
$[78] = handleFileSelect;
|
|
1224
|
+
$[79] = maxFileSize;
|
|
1225
|
+
$[80] = uploadDialogOpen;
|
|
1226
|
+
$[81] = t38;
|
|
1227
|
+
} else {
|
|
1228
|
+
t38 = $[81];
|
|
1229
|
+
}
|
|
1230
|
+
let t39;
|
|
1231
|
+
if ($[82] !== t34 || $[83] !== t35 || $[84] !== t36 || $[85] !== t38) {
|
|
1232
|
+
t39 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col overflow-hidden", children: [
|
|
1233
|
+
t34,
|
|
1234
|
+
t35,
|
|
1235
|
+
t36,
|
|
1236
|
+
t38
|
|
1237
|
+
] });
|
|
1238
|
+
$[82] = t34;
|
|
1239
|
+
$[83] = t35;
|
|
1240
|
+
$[84] = t36;
|
|
1241
|
+
$[85] = t38;
|
|
1242
|
+
$[86] = t39;
|
|
1243
|
+
} else {
|
|
1244
|
+
t39 = $[86];
|
|
1245
|
+
}
|
|
1246
|
+
return t39;
|
|
1247
|
+
}
|
|
1248
|
+
const mediaManagerTranslationsEn = {
|
|
1249
|
+
media_library: "Media Library",
|
|
1250
|
+
media_library_description: "Manage images and files",
|
|
1251
|
+
media_search_assets: "Search assets...",
|
|
1252
|
+
media_grid_view: "Grid view",
|
|
1253
|
+
media_list_view: "List view",
|
|
1254
|
+
media_refresh: "Refresh",
|
|
1255
|
+
media_upload: "Upload",
|
|
1256
|
+
media_error_loading: "Error loading assets: {{message}}",
|
|
1257
|
+
media_try_again: "Try Again",
|
|
1258
|
+
media_no_assets: "No media assets yet",
|
|
1259
|
+
media_upload_first_file: "Upload your first file",
|
|
1260
|
+
media_asset_updated: "Asset updated successfully",
|
|
1261
|
+
media_error_updating: "Error updating asset: {{message}}",
|
|
1262
|
+
media_asset_deleted: "Asset deleted successfully",
|
|
1263
|
+
media_error_deleting: "Error deleting asset: {{message}}",
|
|
1264
|
+
media_error_getting_url: "Error getting download URL",
|
|
1265
|
+
media_preview_not_available: "Preview not available",
|
|
1266
|
+
media_dimensions: "Dimensions",
|
|
1267
|
+
media_size: "Size",
|
|
1268
|
+
media_type: "Type",
|
|
1269
|
+
media_created: "Created",
|
|
1270
|
+
media_file_name: "File Name",
|
|
1271
|
+
media_title: "Title",
|
|
1272
|
+
media_alt_text: "Alt Text",
|
|
1273
|
+
media_recommended_seo: "Recommended for SEO",
|
|
1274
|
+
media_caption: "Caption",
|
|
1275
|
+
media_tags: "Tags",
|
|
1276
|
+
media_add_tag: "Add a tag...",
|
|
1277
|
+
media_add: "Add",
|
|
1278
|
+
media_save_changes: "Save Changes",
|
|
1279
|
+
media_delete_asset: "Delete Asset?",
|
|
1280
|
+
media_delete_confirmation: 'Are you sure you want to delete "{{name}}"? This action cannot be undone.',
|
|
1281
|
+
media_file_too_large: "{{name}}: File too large (max {{size}})",
|
|
1282
|
+
media_file_type_not_allowed: "{{name}}: File type not allowed",
|
|
1283
|
+
media_upload_failed: "Upload failed",
|
|
1284
|
+
media_upload_files: "Upload Files",
|
|
1285
|
+
media_drop_files: "Drop files here or click to browse",
|
|
1286
|
+
media_max_file_size: "Maximum file size: {{size}}",
|
|
1287
|
+
media_selected_files_count: "Selected files ({{count}})",
|
|
1288
|
+
media_remove: "Remove",
|
|
1289
|
+
media_uploading: "Uploading...",
|
|
1290
|
+
media_manage_description: "Manage your media files and assets",
|
|
1291
|
+
media_assets_count: "{{count}} assets"
|
|
1292
|
+
};
|
|
1293
|
+
const mediaManagerTranslationsEs = {
|
|
1294
|
+
media_library: "Biblioteca de Medios",
|
|
1295
|
+
media_library_description: "Gestionar imágenes y archivos",
|
|
1296
|
+
media_search_assets: "Buscar recursos...",
|
|
1297
|
+
media_grid_view: "Vista de cuadrícula",
|
|
1298
|
+
media_list_view: "Vista de lista",
|
|
1299
|
+
media_refresh: "Actualizar",
|
|
1300
|
+
media_upload: "Subir",
|
|
1301
|
+
media_error_loading: "Error al cargar recursos: {{message}}",
|
|
1302
|
+
media_try_again: "Volver a intentar",
|
|
1303
|
+
media_no_assets: "Aún no hay recursos multimedia",
|
|
1304
|
+
media_upload_first_file: "Sube tu primer archivo",
|
|
1305
|
+
media_asset_updated: "Recurso actualizado con éxito",
|
|
1306
|
+
media_error_updating: "Error al actualizar recurso: {{message}}",
|
|
1307
|
+
media_asset_deleted: "Recurso eliminado con éxito",
|
|
1308
|
+
media_error_deleting: "Error al eliminar recurso: {{message}}",
|
|
1309
|
+
media_error_getting_url: "Error al obtener URL de descarga",
|
|
1310
|
+
media_preview_not_available: "Vista previa no disponible",
|
|
1311
|
+
media_dimensions: "Dimensiones",
|
|
1312
|
+
media_size: "Tamaño",
|
|
1313
|
+
media_type: "Tipo",
|
|
1314
|
+
media_created: "Creado",
|
|
1315
|
+
media_file_name: "Nombre del archivo",
|
|
1316
|
+
media_title: "Título",
|
|
1317
|
+
media_alt_text: "Texto alternativo",
|
|
1318
|
+
media_recommended_seo: "Recomendado para SEO",
|
|
1319
|
+
media_caption: "Leyenda",
|
|
1320
|
+
media_tags: "Etiquetas",
|
|
1321
|
+
media_add_tag: "Añadir una etiqueta...",
|
|
1322
|
+
media_add: "Añadir",
|
|
1323
|
+
media_save_changes: "Guardar cambios",
|
|
1324
|
+
media_delete_asset: "¿Eliminar recurso?",
|
|
1325
|
+
media_delete_confirmation: '¿Estás seguro de que deseas eliminar "{{name}}"? Esta acción no se puede deshacer.',
|
|
1326
|
+
media_file_too_large: "{{name}}: Archivo demasiado grande (máx. {{size}})",
|
|
1327
|
+
media_file_type_not_allowed: "{{name}}: Tipo de archivo no permitido",
|
|
1328
|
+
media_upload_failed: "Error al subir",
|
|
1329
|
+
media_upload_files: "Subir archivos",
|
|
1330
|
+
media_drop_files: "Suelta archivos aquí o haz clic para buscar",
|
|
1331
|
+
media_max_file_size: "Tamaño máximo de archivo: {{size}}",
|
|
1332
|
+
media_selected_files_count: "Archivos seleccionados ({{count}})",
|
|
1333
|
+
media_remove: "Quitar",
|
|
1334
|
+
media_uploading: "Subiendo...",
|
|
1335
|
+
media_manage_description: "Gestiona tus archivos y recursos multimedia",
|
|
1336
|
+
media_assets_count: "{{count}} recursos"
|
|
1337
|
+
};
|
|
1338
|
+
const mediaManagerTranslationsDe = {
|
|
1339
|
+
media_library: "Mediathek",
|
|
1340
|
+
media_library_description: "Bilder und Dateien verwalten",
|
|
1341
|
+
media_search_assets: "Assets durchsuchen...",
|
|
1342
|
+
media_grid_view: "Rasteransicht",
|
|
1343
|
+
media_list_view: "Listenansicht",
|
|
1344
|
+
media_refresh: "Aktualisieren",
|
|
1345
|
+
media_upload: "Hochladen",
|
|
1346
|
+
media_error_loading: "Fehler beim Laden der Assets: {{message}}",
|
|
1347
|
+
media_try_again: "Erneut versuchen",
|
|
1348
|
+
media_no_assets: "Noch keine Medien-Assets",
|
|
1349
|
+
media_upload_first_file: "Laden Sie Ihre erste Datei hoch",
|
|
1350
|
+
media_asset_updated: "Asset erfolgreich aktualisiert",
|
|
1351
|
+
media_error_updating: "Fehler beim Aktualisieren des Assets: {{message}}",
|
|
1352
|
+
media_asset_deleted: "Asset erfolgreich gelöscht",
|
|
1353
|
+
media_error_deleting: "Fehler beim Löschen des Assets: {{message}}",
|
|
1354
|
+
media_error_getting_url: "Fehler beim Abrufen der Download-URL",
|
|
1355
|
+
media_preview_not_available: "Vorschau nicht verfügbar",
|
|
1356
|
+
media_dimensions: "Abmessungen",
|
|
1357
|
+
media_size: "Größe",
|
|
1358
|
+
media_type: "Typ",
|
|
1359
|
+
media_created: "Erstellt",
|
|
1360
|
+
media_file_name: "Dateiname",
|
|
1361
|
+
media_title: "Titel",
|
|
1362
|
+
media_alt_text: "Alternativtext",
|
|
1363
|
+
media_recommended_seo: "Empfohlen für SEO",
|
|
1364
|
+
media_caption: "Bildunterschrift",
|
|
1365
|
+
media_tags: "Schlagwörter",
|
|
1366
|
+
media_add_tag: "Schlagwort hinzufügen...",
|
|
1367
|
+
media_add: "Hinzufügen",
|
|
1368
|
+
media_save_changes: "Änderungen speichern",
|
|
1369
|
+
media_delete_asset: "Asset löschen?",
|
|
1370
|
+
media_delete_confirmation: 'Sind Sie sicher, dass Sie "{{name}}" löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.',
|
|
1371
|
+
media_file_too_large: "{{name}}: Datei ist zu groß (max. {{size}})",
|
|
1372
|
+
media_file_type_not_allowed: "{{name}}: Dateityp nicht zulässig",
|
|
1373
|
+
media_upload_failed: "Hochladen fehlgeschlagen",
|
|
1374
|
+
media_upload_files: "Dateien hochladen",
|
|
1375
|
+
media_drop_files: "Dateien hier ablegen oder zum Durchsuchen klicken",
|
|
1376
|
+
media_max_file_size: "Maximale Dateigröße: {{size}}",
|
|
1377
|
+
media_selected_files_count: "Ausgewählte Dateien ({{count}})",
|
|
1378
|
+
media_remove: "Entfernen",
|
|
1379
|
+
media_uploading: "Wird hochgeladen...",
|
|
1380
|
+
media_manage_description: "Verwalten Sie Ihre Mediendateien und Assets",
|
|
1381
|
+
media_assets_count: "{{count}} Assets"
|
|
1382
|
+
};
|
|
1383
|
+
const mediaManagerTranslationsFr = {
|
|
1384
|
+
media_library: "Médiathèque",
|
|
1385
|
+
media_library_description: "Gérer les images et les fichiers",
|
|
1386
|
+
media_search_assets: "Rechercher des éléments...",
|
|
1387
|
+
media_grid_view: "Vue en grille",
|
|
1388
|
+
media_list_view: "Vue en liste",
|
|
1389
|
+
media_refresh: "Rafraîchir",
|
|
1390
|
+
media_upload: "Télécharger",
|
|
1391
|
+
media_error_loading: "Erreur lors du chargement des éléments : {{message}}",
|
|
1392
|
+
media_try_again: "Réessayer",
|
|
1393
|
+
media_no_assets: "Pas encore d'éléments multimédias",
|
|
1394
|
+
media_upload_first_file: "Téléchargez votre premier fichier",
|
|
1395
|
+
media_asset_updated: "Élément mis à jour avec succès",
|
|
1396
|
+
media_error_updating: "Erreur lors de la mise à jour de l'élément : {{message}}",
|
|
1397
|
+
media_asset_deleted: "Élément supprimé avec succès",
|
|
1398
|
+
media_error_deleting: "Erreur lors de la suppression de l'élément : {{message}}",
|
|
1399
|
+
media_error_getting_url: "Erreur lors de l'obtention de l'URL de téléchargement",
|
|
1400
|
+
media_preview_not_available: "Aperçu non disponible",
|
|
1401
|
+
media_dimensions: "Dimensions",
|
|
1402
|
+
media_size: "Taille",
|
|
1403
|
+
media_type: "Type",
|
|
1404
|
+
media_created: "Créé",
|
|
1405
|
+
media_file_name: "Nom du fichier",
|
|
1406
|
+
media_title: "Titre",
|
|
1407
|
+
media_alt_text: "Texte alternatif",
|
|
1408
|
+
media_recommended_seo: "Recommandé pour le référencement (SEO)",
|
|
1409
|
+
media_caption: "Légende",
|
|
1410
|
+
media_tags: "Balises",
|
|
1411
|
+
media_add_tag: "Ajouter une balise...",
|
|
1412
|
+
media_add: "Ajouter",
|
|
1413
|
+
media_save_changes: "Enregistrer les modifications",
|
|
1414
|
+
media_delete_asset: "Supprimer l'élément ?",
|
|
1415
|
+
media_delete_confirmation: 'Êtes-vous sûr de vouloir supprimer "{{name}}" ? Cette action ne peut pas être annulée.',
|
|
1416
|
+
media_file_too_large: "{{name}} : Fichier trop volumineux (max {{size}})",
|
|
1417
|
+
media_file_type_not_allowed: "{{name}} : Type de fichier non autorisé",
|
|
1418
|
+
media_upload_failed: "Le téléchargement a échoué",
|
|
1419
|
+
media_upload_files: "Télécharger des fichiers",
|
|
1420
|
+
media_drop_files: "Déposez les fichiers ici ou cliquez pour parcourir",
|
|
1421
|
+
media_max_file_size: "Taille maximale du fichier : {{size}}",
|
|
1422
|
+
media_selected_files_count: "Fichiers sélectionnés ({{count}})",
|
|
1423
|
+
media_remove: "Retirer",
|
|
1424
|
+
media_uploading: "Téléchargement en cours...",
|
|
1425
|
+
media_manage_description: "Gérez vos fichiers et éléments multimédias",
|
|
1426
|
+
media_assets_count: "{{count}} éléments"
|
|
1427
|
+
};
|
|
1428
|
+
const mediaManagerTranslationsIt = {
|
|
1429
|
+
media_library: "Libreria multimediale",
|
|
1430
|
+
media_library_description: "Gestisci immagini e file",
|
|
1431
|
+
media_search_assets: "Cerca risorse...",
|
|
1432
|
+
media_grid_view: "Visualizzazione griglia",
|
|
1433
|
+
media_list_view: "Visualizzazione elenco",
|
|
1434
|
+
media_refresh: "Aggiorna",
|
|
1435
|
+
media_upload: "Carica",
|
|
1436
|
+
media_error_loading: "Errore durante il caricamento delle risorse: {{message}}",
|
|
1437
|
+
media_try_again: "Riprova",
|
|
1438
|
+
media_no_assets: "Nessuna risorsa multimediale ancora presente",
|
|
1439
|
+
media_upload_first_file: "Carica il tuo primo file",
|
|
1440
|
+
media_asset_updated: "Risorsa aggiornata con successo",
|
|
1441
|
+
media_error_updating: "Errore durante l'aggiornamento della risorsa: {{message}}",
|
|
1442
|
+
media_asset_deleted: "Risorsa eliminata con successo",
|
|
1443
|
+
media_error_deleting: "Errore durante l'eliminazione della risorsa: {{message}}",
|
|
1444
|
+
media_error_getting_url: "Errore durante il recupero dell'URL di download",
|
|
1445
|
+
media_preview_not_available: "Anteprima non disponibile",
|
|
1446
|
+
media_dimensions: "Dimensioni",
|
|
1447
|
+
media_size: "Dimensione",
|
|
1448
|
+
media_type: "Tipo",
|
|
1449
|
+
media_created: "Creato",
|
|
1450
|
+
media_file_name: "Nome file",
|
|
1451
|
+
media_title: "Titolo",
|
|
1452
|
+
media_alt_text: "Testo alternativo",
|
|
1453
|
+
media_recommended_seo: "Consigliato per la SEO",
|
|
1454
|
+
media_caption: "Didascalia",
|
|
1455
|
+
media_tags: "Tag",
|
|
1456
|
+
media_add_tag: "Aggiungi un tag...",
|
|
1457
|
+
media_add: "Aggiungi",
|
|
1458
|
+
media_save_changes: "Salva modifiche",
|
|
1459
|
+
media_delete_asset: "Elimina risorsa?",
|
|
1460
|
+
media_delete_confirmation: 'Sei sicuro di voler eliminare "{{name}}"? Questa azione non può essere annullata.',
|
|
1461
|
+
media_file_too_large: "{{name}}: File troppo grande (max {{size}})",
|
|
1462
|
+
media_file_type_not_allowed: "{{name}}: Tipo di file non consentito",
|
|
1463
|
+
media_upload_failed: "Caricamento fallito",
|
|
1464
|
+
media_upload_files: "Carica file",
|
|
1465
|
+
media_drop_files: "Rilascia i file qui o fai clic per sfogliare",
|
|
1466
|
+
media_max_file_size: "Dimensione massima del file: {{size}}",
|
|
1467
|
+
media_selected_files_count: "File selezionati ({{count}})",
|
|
1468
|
+
media_remove: "Rimuovi",
|
|
1469
|
+
media_uploading: "Caricamento in corso...",
|
|
1470
|
+
media_manage_description: "Gestisci i tuoi file e risorse multimediali",
|
|
1471
|
+
media_assets_count: "{{count}} risorse"
|
|
1472
|
+
};
|
|
1473
|
+
const mediaManagerTranslationsHi = {
|
|
1474
|
+
media_library: "मीडिया लाइब्रेरी",
|
|
1475
|
+
media_library_description: "चित्र और फ़ाइलें प्रबंधित करें",
|
|
1476
|
+
media_search_assets: "संपत्तियां खोजें...",
|
|
1477
|
+
media_grid_view: "ग्रिड दृश्य",
|
|
1478
|
+
media_list_view: "सूची दृश्य",
|
|
1479
|
+
media_refresh: "रीफ्रेश करें",
|
|
1480
|
+
media_upload: "अपलोड करें",
|
|
1481
|
+
media_error_loading: "संपत्तियों को लोड करने में त्रुटि: {{message}}",
|
|
1482
|
+
media_try_again: "पुनः प्रयास करें",
|
|
1483
|
+
media_no_assets: "अभी तक कोई मीडिया संपत्ति नहीं",
|
|
1484
|
+
media_upload_first_file: "अपनी पहली फ़ाइल अपलोड करें",
|
|
1485
|
+
media_asset_updated: "संपत्ति सफलतापूर्वक अपडेट की गई",
|
|
1486
|
+
media_error_updating: "संपत्ति को अपडेट करने में त्रुटि: {{message}}",
|
|
1487
|
+
media_asset_deleted: "संपत्ति सफलतापूर्वक हटा दी गई",
|
|
1488
|
+
media_error_deleting: "संपत्ति को हटाने में त्रुटि: {{message}}",
|
|
1489
|
+
media_error_getting_url: "डाउनलोड URL प्राप्त करने में त्रुटि",
|
|
1490
|
+
media_preview_not_available: "पूर्वावलोकन उपलब्ध नहीं है",
|
|
1491
|
+
media_dimensions: "आयाम",
|
|
1492
|
+
media_size: "आकार",
|
|
1493
|
+
media_type: "प्रकार",
|
|
1494
|
+
media_created: "बनाया गया",
|
|
1495
|
+
media_file_name: "फ़ाइल का नाम",
|
|
1496
|
+
media_title: "शीर्षक",
|
|
1497
|
+
media_alt_text: "वैकल्पिक पाठ",
|
|
1498
|
+
media_recommended_seo: "SEO के लिए अनुशंसित",
|
|
1499
|
+
media_caption: "कैप्शन",
|
|
1500
|
+
media_tags: "टैग",
|
|
1501
|
+
media_add_tag: "एक टैग जोड़ें...",
|
|
1502
|
+
media_add: "जोड़ें",
|
|
1503
|
+
media_save_changes: "परिवर्तन सहेजें",
|
|
1504
|
+
media_delete_asset: "संपत्ति हटाएं?",
|
|
1505
|
+
media_delete_confirmation: 'क्या आप निश्चित रूप से "{{name}}" को हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती।',
|
|
1506
|
+
media_file_too_large: "{{name}}: फ़ाइल बहुत बड़ी है (अधिकतम {{size}})",
|
|
1507
|
+
media_file_type_not_allowed: "{{name}}: फ़ाइल प्रकार की अनुमति नहीं है",
|
|
1508
|
+
media_upload_failed: "अपलोड विफल रहा",
|
|
1509
|
+
media_upload_files: "फ़ाइलें अपलोड करें",
|
|
1510
|
+
media_drop_files: "फ़ाइलें यहाँ छोड़ें या ब्राउज़ करने के लिए क्लिक करें",
|
|
1511
|
+
media_max_file_size: "अधिकतम फ़ाइल आकार: {{size}}",
|
|
1512
|
+
media_selected_files_count: "चयनित फ़ाइलें ({{count}})",
|
|
1513
|
+
media_remove: "हटाएं",
|
|
1514
|
+
media_uploading: "अपलोड हो रहा है...",
|
|
1515
|
+
media_manage_description: "अपनी मीडिया फ़ाइलें और संपत्तियां प्रबंधित करें",
|
|
1516
|
+
media_assets_count: "{{count}} संपत्तियां"
|
|
1517
|
+
};
|
|
1518
|
+
const mediaManagerTranslationsPt = {
|
|
1519
|
+
media_library: "Biblioteca de Média",
|
|
1520
|
+
media_library_description: "Gerir imagens e ficheiros",
|
|
1521
|
+
media_search_assets: "Pesquisar recursos...",
|
|
1522
|
+
media_grid_view: "Vista em grelha",
|
|
1523
|
+
media_list_view: "Vista em lista",
|
|
1524
|
+
media_refresh: "Atualizar",
|
|
1525
|
+
media_upload: "Carregar",
|
|
1526
|
+
media_error_loading: "Erro ao carregar recursos: {{message}}",
|
|
1527
|
+
media_try_again: "Tentar Novamente",
|
|
1528
|
+
media_no_assets: "Ainda não há recursos de média",
|
|
1529
|
+
media_upload_first_file: "Carregue o seu primeiro ficheiro",
|
|
1530
|
+
media_asset_updated: "Recurso atualizado com sucesso",
|
|
1531
|
+
media_error_updating: "Erro ao atualizar recurso: {{message}}",
|
|
1532
|
+
media_asset_deleted: "Recurso eliminado com sucesso",
|
|
1533
|
+
media_error_deleting: "Erro ao eliminar recurso: {{message}}",
|
|
1534
|
+
media_error_getting_url: "Erro ao obter URL de download",
|
|
1535
|
+
media_preview_not_available: "Pré-visualização não disponível",
|
|
1536
|
+
media_dimensions: "Dimensões",
|
|
1537
|
+
media_size: "Tamanho",
|
|
1538
|
+
media_type: "Tipo",
|
|
1539
|
+
media_created: "Criado",
|
|
1540
|
+
media_file_name: "Nome do Ficheiro",
|
|
1541
|
+
media_title: "Título",
|
|
1542
|
+
media_alt_text: "Texto Alternativo",
|
|
1543
|
+
media_recommended_seo: "Recomendado para SEO",
|
|
1544
|
+
media_caption: "Legenda",
|
|
1545
|
+
media_tags: "Etiquetas",
|
|
1546
|
+
media_add_tag: "Adicionar uma etiqueta...",
|
|
1547
|
+
media_add: "Adicionar",
|
|
1548
|
+
media_save_changes: "Guardar Alterações",
|
|
1549
|
+
media_delete_asset: "Eliminar Recurso?",
|
|
1550
|
+
media_delete_confirmation: 'Tem a certeza de que quer eliminar "{{name}}"? Esta ação não pode ser desfeita.',
|
|
1551
|
+
media_file_too_large: "{{name}}: Ficheiro demasiado grande (máx {{size}})",
|
|
1552
|
+
media_file_type_not_allowed: "{{name}}: Tipo de ficheiro não permitido",
|
|
1553
|
+
media_upload_failed: "Falha no carregamento",
|
|
1554
|
+
media_upload_files: "Carregar Ficheiros",
|
|
1555
|
+
media_drop_files: "Solte ficheiros aqui ou clique para navegar",
|
|
1556
|
+
media_max_file_size: "Tamanho máximo de ficheiro: {{size}}",
|
|
1557
|
+
media_selected_files_count: "Ficheiros selecionados ({{count}})",
|
|
1558
|
+
media_remove: "Remover",
|
|
1559
|
+
media_uploading: "A carregar...",
|
|
1560
|
+
media_manage_description: "Gerir os seus ficheiros e recursos de média",
|
|
1561
|
+
media_assets_count: "{{count}} recursos"
|
|
1562
|
+
};
|
|
1563
|
+
const DEFAULT_STORAGE_PATH = "media";
|
|
1564
|
+
const DEFAULT_COLLECTION_PATH = "media_assets";
|
|
1565
|
+
const MediaManagerConfigContext = react.createContext(null);
|
|
1566
|
+
function useMediaManagerConfig() {
|
|
1567
|
+
const config = react.useContext(MediaManagerConfigContext);
|
|
1568
|
+
if (!config) {
|
|
1569
|
+
throw new Error("useMediaManagerConfig must be used within MediaManagerConfigProvider");
|
|
1570
|
+
}
|
|
1571
|
+
return config;
|
|
1572
|
+
}
|
|
1573
|
+
function MediaLibraryViewInternal() {
|
|
1574
|
+
const $ = reactCompilerRuntime.c(14);
|
|
1575
|
+
const config = useMediaManagerConfig();
|
|
1576
|
+
const t0 = config.storagePath ?? DEFAULT_STORAGE_PATH;
|
|
1577
|
+
const t1 = config.collectionPath ?? DEFAULT_COLLECTION_PATH;
|
|
1578
|
+
let t2;
|
|
1579
|
+
if ($[0] !== config.bucket || $[1] !== config.dataSourceDelegate || $[2] !== config.storageSource || $[3] !== config.thumbnailPath || $[4] !== config.thumbnailSizes || $[5] !== t0 || $[6] !== t1) {
|
|
1580
|
+
t2 = {
|
|
1581
|
+
storageSource: config.storageSource,
|
|
1582
|
+
dataSourceDelegate: config.dataSourceDelegate,
|
|
1583
|
+
storagePath: t0,
|
|
1584
|
+
collectionPath: t1,
|
|
1585
|
+
bucket: config.bucket,
|
|
1586
|
+
thumbnailSizes: config.thumbnailSizes,
|
|
1587
|
+
thumbnailPath: config.thumbnailPath
|
|
1588
|
+
};
|
|
1589
|
+
$[0] = config.bucket;
|
|
1590
|
+
$[1] = config.dataSourceDelegate;
|
|
1591
|
+
$[2] = config.storageSource;
|
|
1592
|
+
$[3] = config.thumbnailPath;
|
|
1593
|
+
$[4] = config.thumbnailSizes;
|
|
1594
|
+
$[5] = t0;
|
|
1595
|
+
$[6] = t1;
|
|
1596
|
+
$[7] = t2;
|
|
1597
|
+
} else {
|
|
1598
|
+
t2 = $[7];
|
|
1599
|
+
}
|
|
1600
|
+
const controller = useMediaManagerController(t2);
|
|
1601
|
+
let t3;
|
|
1602
|
+
if ($[8] !== config.acceptedMimeTypes || $[9] !== config.maxFileSize) {
|
|
1603
|
+
t3 = /* @__PURE__ */ jsxRuntime.jsx(MediaLibraryView, { maxFileSize: config.maxFileSize, acceptedMimeTypes: config.acceptedMimeTypes });
|
|
1604
|
+
$[8] = config.acceptedMimeTypes;
|
|
1605
|
+
$[9] = config.maxFileSize;
|
|
1606
|
+
$[10] = t3;
|
|
1607
|
+
} else {
|
|
1608
|
+
t3 = $[10];
|
|
1609
|
+
}
|
|
1610
|
+
let t4;
|
|
1611
|
+
if ($[11] !== controller || $[12] !== t3) {
|
|
1612
|
+
t4 = /* @__PURE__ */ jsxRuntime.jsx(MediaManagerProvider, { controller, children: t3 });
|
|
1613
|
+
$[11] = controller;
|
|
1614
|
+
$[12] = t3;
|
|
1615
|
+
$[13] = t4;
|
|
1616
|
+
} else {
|
|
1617
|
+
t4 = $[13];
|
|
1618
|
+
}
|
|
1619
|
+
return t4;
|
|
1620
|
+
}
|
|
1621
|
+
function buildMediaView() {
|
|
1622
|
+
return {
|
|
1623
|
+
path: "media",
|
|
1624
|
+
name: "Media Library",
|
|
1625
|
+
description: "Manage your media files",
|
|
1626
|
+
group: "Media",
|
|
1627
|
+
icon: "perm_media",
|
|
1628
|
+
view: /* @__PURE__ */ jsxRuntime.jsx(MediaLibraryViewInternal, {})
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
function useMediaManagerPlugin(props) {
|
|
1632
|
+
const mediaView = react.useMemo(() => buildMediaView(), []);
|
|
1633
|
+
return react.useMemo(() => ({
|
|
1634
|
+
key: "media_manager",
|
|
1635
|
+
views: [mediaView],
|
|
1636
|
+
provider: {
|
|
1637
|
+
Component: ({
|
|
1638
|
+
children
|
|
1639
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(MediaManagerConfigContext.Provider, { value: props, children })
|
|
1640
|
+
},
|
|
1641
|
+
i18n: {
|
|
1642
|
+
en: mediaManagerTranslationsEn,
|
|
1643
|
+
es: mediaManagerTranslationsEs,
|
|
1644
|
+
de: mediaManagerTranslationsDe,
|
|
1645
|
+
fr: mediaManagerTranslationsFr,
|
|
1646
|
+
it: mediaManagerTranslationsIt,
|
|
1647
|
+
hi: mediaManagerTranslationsHi,
|
|
1648
|
+
pt: mediaManagerTranslationsPt
|
|
1649
|
+
}
|
|
1650
|
+
}), []);
|
|
1651
|
+
}
|
|
1652
|
+
function MediaLibraryCard(t0) {
|
|
1653
|
+
const $ = reactCompilerRuntime.c(13);
|
|
1654
|
+
const {
|
|
1655
|
+
group
|
|
1656
|
+
} = t0;
|
|
1657
|
+
const {
|
|
1658
|
+
t
|
|
1659
|
+
} = core.useTranslation();
|
|
1660
|
+
if (group !== "Media") {
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
let t1;
|
|
1664
|
+
if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1665
|
+
t1 = ui.cls("p-4 cursor-pointer", "hover:bg-surface-accent-100 dark:hover:bg-surface-accent-800", "transition-colors duration-200", "flex flex-col gap-2");
|
|
1666
|
+
$[0] = t1;
|
|
1667
|
+
} else {
|
|
1668
|
+
t1 = $[0];
|
|
1669
|
+
}
|
|
1670
|
+
let t2;
|
|
1671
|
+
if ($[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
|
|
1672
|
+
t2 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.cls("w-10 h-10 rounded-lg", "bg-primary/10 dark:bg-primary/20", "flex items-center justify-center"), children: /* @__PURE__ */ jsxRuntime.jsx(ui.ImageIcon, { className: "text-primary", size: "medium" }) });
|
|
1673
|
+
$[1] = t2;
|
|
1674
|
+
} else {
|
|
1675
|
+
t2 = $[1];
|
|
1676
|
+
}
|
|
1677
|
+
let t3;
|
|
1678
|
+
if ($[2] !== t) {
|
|
1679
|
+
t3 = t("media_library");
|
|
1680
|
+
$[2] = t;
|
|
1681
|
+
$[3] = t3;
|
|
1682
|
+
} else {
|
|
1683
|
+
t3 = $[3];
|
|
1684
|
+
}
|
|
1685
|
+
let t4;
|
|
1686
|
+
if ($[4] !== t3) {
|
|
1687
|
+
t4 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", className: "font-medium", children: t3 });
|
|
1688
|
+
$[4] = t3;
|
|
1689
|
+
$[5] = t4;
|
|
1690
|
+
} else {
|
|
1691
|
+
t4 = $[5];
|
|
1692
|
+
}
|
|
1693
|
+
let t5;
|
|
1694
|
+
if ($[6] !== t) {
|
|
1695
|
+
t5 = t("media_library_description");
|
|
1696
|
+
$[6] = t;
|
|
1697
|
+
$[7] = t5;
|
|
1698
|
+
} else {
|
|
1699
|
+
t5 = $[7];
|
|
1700
|
+
}
|
|
1701
|
+
let t6;
|
|
1702
|
+
if ($[8] !== t5) {
|
|
1703
|
+
t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-surface-accent-600 dark:text-surface-accent-400", children: t5 });
|
|
1704
|
+
$[8] = t5;
|
|
1705
|
+
$[9] = t6;
|
|
1706
|
+
} else {
|
|
1707
|
+
t6 = $[9];
|
|
1708
|
+
}
|
|
1709
|
+
let t7;
|
|
1710
|
+
if ($[10] !== t4 || $[11] !== t6) {
|
|
1711
|
+
t7 = /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: "/media", className: "no-underline", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { className: t1, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1712
|
+
t2,
|
|
1713
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
1714
|
+
t4,
|
|
1715
|
+
t6
|
|
1716
|
+
] })
|
|
1717
|
+
] }) }) });
|
|
1718
|
+
$[10] = t4;
|
|
1719
|
+
$[11] = t6;
|
|
1720
|
+
$[12] = t7;
|
|
1721
|
+
} else {
|
|
1722
|
+
t7 = $[12];
|
|
1723
|
+
}
|
|
1724
|
+
return t7;
|
|
1725
|
+
}
|
|
1726
|
+
exports2.MediaAssetCard = MediaAssetCard;
|
|
1727
|
+
exports2.MediaAssetDetails = MediaAssetDetails;
|
|
1728
|
+
exports2.MediaLibraryCard = MediaLibraryCard;
|
|
1729
|
+
exports2.MediaLibraryView = MediaLibraryView;
|
|
1730
|
+
exports2.MediaManagerProvider = MediaManagerProvider;
|
|
1731
|
+
exports2.MediaUploadDialog = MediaUploadDialog;
|
|
1732
|
+
exports2.useMediaManager = useMediaManager;
|
|
1733
|
+
exports2.useMediaManagerController = useMediaManagerController;
|
|
1734
|
+
exports2.useMediaManagerPlugin = useMediaManagerPlugin;
|
|
1735
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
1736
|
+
}));
|
|
1737
|
+
//# sourceMappingURL=index.umd.js.map
|