@gallop.software/studio 0.1.86 → 0.1.88
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/{StudioUI-QTKNMFLF.mjs → StudioUI-6CQ7MX7R.mjs} +101 -27
- package/dist/StudioUI-6CQ7MX7R.mjs.map +1 -0
- package/dist/{StudioUI-PH265HCB.js → StudioUI-Y35A2T7S.js} +107 -33
- package/dist/StudioUI-Y35A2T7S.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/StudioUI-PH265HCB.js.map +0 -1
- package/dist/StudioUI-QTKNMFLF.mjs.map +0 -1
|
@@ -310,6 +310,23 @@ var progressStyles = {
|
|
|
310
310
|
white-space: nowrap;
|
|
311
311
|
overflow: hidden;
|
|
312
312
|
text-overflow: ellipsis;
|
|
313
|
+
`,
|
|
314
|
+
errorList: css`
|
|
315
|
+
margin-top: 12px;
|
|
316
|
+
padding: 12px;
|
|
317
|
+
background: #fef2f2;
|
|
318
|
+
border: 1px solid #fecaca;
|
|
319
|
+
border-radius: 6px;
|
|
320
|
+
max-height: 200px;
|
|
321
|
+
overflow-y: auto;
|
|
322
|
+
`,
|
|
323
|
+
errorItem: css`
|
|
324
|
+
font-size: ${fontSize.xs};
|
|
325
|
+
color: #991b1b;
|
|
326
|
+
margin: 0 0 4px;
|
|
327
|
+
&:last-child {
|
|
328
|
+
margin-bottom: 0;
|
|
329
|
+
}
|
|
313
330
|
`
|
|
314
331
|
};
|
|
315
332
|
function ProgressModal({
|
|
@@ -331,26 +348,36 @@ function ProgressModal({
|
|
|
331
348
|
" image",
|
|
332
349
|
(progress.processed ?? progress.current) !== 1 ? "s" : "",
|
|
333
350
|
" before stopping."
|
|
334
|
-
] }) : isComplete ? /* @__PURE__ */ jsxs(
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
351
|
+
] }) : isComplete ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
352
|
+
/* @__PURE__ */ jsxs("p", { css: styles.message, children: [
|
|
353
|
+
"Processed ",
|
|
354
|
+
progress.processed,
|
|
355
|
+
" image",
|
|
356
|
+
progress.processed !== 1 ? "s" : "",
|
|
357
|
+
".",
|
|
358
|
+
progress.orphansRemoved !== void 0 && progress.orphansRemoved > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
359
|
+
" Removed ",
|
|
360
|
+
progress.orphansRemoved,
|
|
361
|
+
" orphaned thumbnail",
|
|
362
|
+
progress.orphansRemoved !== 1 ? "s" : "",
|
|
363
|
+
"."
|
|
364
|
+
] }) : null,
|
|
365
|
+
progress.errors !== void 0 && progress.errors > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
366
|
+
" ",
|
|
367
|
+
progress.errors,
|
|
368
|
+
" error",
|
|
369
|
+
progress.errors !== 1 ? "s" : "",
|
|
370
|
+
" occurred."
|
|
371
|
+
] }) : null
|
|
372
|
+
] }),
|
|
373
|
+
progress.errorMessages && progress.errorMessages.length > 0 && /* @__PURE__ */ jsxs("div", { css: progressStyles.errorList, children: [
|
|
374
|
+
progress.errorMessages.slice(0, 10).map((msg, i) => /* @__PURE__ */ jsx("p", { css: progressStyles.errorItem, children: msg }, i)),
|
|
375
|
+
progress.errorMessages.length > 10 && /* @__PURE__ */ jsxs("p", { css: progressStyles.errorItem, children: [
|
|
376
|
+
"...and ",
|
|
377
|
+
progress.errorMessages.length - 10,
|
|
378
|
+
" more"
|
|
379
|
+
] })
|
|
380
|
+
] })
|
|
354
381
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
355
382
|
/* @__PURE__ */ jsx("p", { css: styles.message, children: progress.status === "cleanup" ? "Cleaning up orphaned files..." : `Processing images...` }),
|
|
356
383
|
/* @__PURE__ */ jsxs("div", { css: progressStyles.progressContainer, children: [
|
|
@@ -1266,6 +1293,8 @@ function StudioToolbar() {
|
|
|
1266
1293
|
const [processing, setProcessing] = useState3(false);
|
|
1267
1294
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState3(false);
|
|
1268
1295
|
const [showProcessConfirm, setShowProcessConfirm] = useState3(false);
|
|
1296
|
+
const [showSyncConfirm, setShowSyncConfirm] = useState3(false);
|
|
1297
|
+
const [syncImageCount, setSyncImageCount] = useState3(0);
|
|
1269
1298
|
const [showProgress, setShowProgress] = useState3(false);
|
|
1270
1299
|
const [progressState, setProgressState] = useState3({
|
|
1271
1300
|
current: 0,
|
|
@@ -1631,7 +1660,7 @@ function StudioToolbar() {
|
|
|
1631
1660
|
});
|
|
1632
1661
|
}
|
|
1633
1662
|
}, [selectedItems, clearSelection, triggerRefresh]);
|
|
1634
|
-
const
|
|
1663
|
+
const handleSyncClick = useCallback(async () => {
|
|
1635
1664
|
if (selectedItems.size === 0) return;
|
|
1636
1665
|
const selectedPaths2 = Array.from(selectedItems);
|
|
1637
1666
|
const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "svg", "ico", "bmp", "tiff", "tif"];
|
|
@@ -1656,14 +1685,42 @@ function StudioToolbar() {
|
|
|
1656
1685
|
console.error("Failed to get folder images:", error);
|
|
1657
1686
|
}
|
|
1658
1687
|
}
|
|
1659
|
-
|
|
1660
|
-
if (imageKeys.length === 0) {
|
|
1688
|
+
if (selectedImagePaths.length === 0) {
|
|
1661
1689
|
setAlertMessage({
|
|
1662
1690
|
title: "No Images Found",
|
|
1663
1691
|
message: "No images found in the selected items."
|
|
1664
1692
|
});
|
|
1665
1693
|
return;
|
|
1666
1694
|
}
|
|
1695
|
+
setSyncImageCount(selectedImagePaths.length);
|
|
1696
|
+
setShowSyncConfirm(true);
|
|
1697
|
+
}, [selectedItems]);
|
|
1698
|
+
const handleSyncConfirm = useCallback(async () => {
|
|
1699
|
+
setShowSyncConfirm(false);
|
|
1700
|
+
const selectedPaths2 = Array.from(selectedItems);
|
|
1701
|
+
const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "svg", "ico", "bmp", "tiff", "tif"];
|
|
1702
|
+
const selectedImagePaths = selectedPaths2.filter((p) => {
|
|
1703
|
+
const ext = p.split(".").pop()?.toLowerCase() || "";
|
|
1704
|
+
return imageExtensions.includes(ext);
|
|
1705
|
+
});
|
|
1706
|
+
const selectedFolders = selectedPaths2.filter((p) => !p.includes(".") || p.endsWith("/"));
|
|
1707
|
+
if (selectedFolders.length > 0) {
|
|
1708
|
+
try {
|
|
1709
|
+
const response = await fetch(`/api/studio/folder-images?folders=${encodeURIComponent(selectedFolders.join(","))}`);
|
|
1710
|
+
const data = await response.json();
|
|
1711
|
+
if (data.images) {
|
|
1712
|
+
for (const img of data.images) {
|
|
1713
|
+
const fullPath = `public/${img}`;
|
|
1714
|
+
if (!selectedImagePaths.includes(fullPath)) {
|
|
1715
|
+
selectedImagePaths.push(fullPath);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
} catch (error) {
|
|
1720
|
+
console.error("Failed to get folder images:", error);
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
const imageKeys = selectedImagePaths.map((p) => "/" + p.replace(/^public\//, ""));
|
|
1667
1724
|
setProgressState({
|
|
1668
1725
|
current: 0,
|
|
1669
1726
|
total: imageKeys.length,
|
|
@@ -1674,6 +1731,7 @@ function StudioToolbar() {
|
|
|
1674
1731
|
setShowProgress(true);
|
|
1675
1732
|
let synced = 0;
|
|
1676
1733
|
let errors = 0;
|
|
1734
|
+
const errorMessages = [];
|
|
1677
1735
|
try {
|
|
1678
1736
|
for (let i = 0; i < imageKeys.length; i++) {
|
|
1679
1737
|
const imageKey = imageKeys[i];
|
|
@@ -1698,13 +1756,18 @@ function StudioToolbar() {
|
|
|
1698
1756
|
return;
|
|
1699
1757
|
}
|
|
1700
1758
|
errors++;
|
|
1759
|
+
errorMessages.push(data.error || `Failed: ${imageKey}`);
|
|
1701
1760
|
} else if (data.synced?.length > 0) {
|
|
1702
1761
|
synced++;
|
|
1703
1762
|
} else if (data.errors?.length > 0) {
|
|
1704
1763
|
errors++;
|
|
1764
|
+
for (const errMsg of data.errors) {
|
|
1765
|
+
errorMessages.push(errMsg);
|
|
1766
|
+
}
|
|
1705
1767
|
}
|
|
1706
|
-
} catch {
|
|
1768
|
+
} catch (err) {
|
|
1707
1769
|
errors++;
|
|
1770
|
+
errorMessages.push(`Network error: ${imageKey}`);
|
|
1708
1771
|
}
|
|
1709
1772
|
}
|
|
1710
1773
|
setProgressState({
|
|
@@ -1713,7 +1776,8 @@ function StudioToolbar() {
|
|
|
1713
1776
|
percent: 100,
|
|
1714
1777
|
status: "complete",
|
|
1715
1778
|
processed: synced,
|
|
1716
|
-
errors
|
|
1779
|
+
errors,
|
|
1780
|
+
errorMessages: errorMessages.length > 0 ? errorMessages : void 0
|
|
1717
1781
|
});
|
|
1718
1782
|
clearSelection();
|
|
1719
1783
|
triggerRefresh();
|
|
@@ -1836,6 +1900,16 @@ function StudioToolbar() {
|
|
|
1836
1900
|
onCancel: () => setShowDeleteConfirm(false)
|
|
1837
1901
|
}
|
|
1838
1902
|
),
|
|
1903
|
+
showSyncConfirm && /* @__PURE__ */ jsx4(
|
|
1904
|
+
ConfirmModal,
|
|
1905
|
+
{
|
|
1906
|
+
title: "Sync to CDN",
|
|
1907
|
+
message: `Sync ${syncImageCount} image${syncImageCount !== 1 ? "s" : ""} to Cloudflare R2? Images must be processed first. After syncing, local thumbnails will be deleted.`,
|
|
1908
|
+
confirmLabel: "Sync",
|
|
1909
|
+
onConfirm: handleSyncConfirm,
|
|
1910
|
+
onCancel: () => setShowSyncConfirm(false)
|
|
1911
|
+
}
|
|
1912
|
+
),
|
|
1839
1913
|
showProcessConfirm && /* @__PURE__ */ jsx4(
|
|
1840
1914
|
ConfirmModal,
|
|
1841
1915
|
{
|
|
@@ -1993,7 +2067,7 @@ function StudioToolbar() {
|
|
|
1993
2067
|
"button",
|
|
1994
2068
|
{
|
|
1995
2069
|
css: styles4.btn,
|
|
1996
|
-
onClick:
|
|
2070
|
+
onClick: handleSyncClick,
|
|
1997
2071
|
disabled: !hasSelection,
|
|
1998
2072
|
children: [
|
|
1999
2073
|
/* @__PURE__ */ jsx4(CloudIcon, {}),
|
|
@@ -4621,4 +4695,4 @@ export {
|
|
|
4621
4695
|
StudioUI,
|
|
4622
4696
|
StudioUI_default as default
|
|
4623
4697
|
};
|
|
4624
|
-
//# sourceMappingURL=StudioUI-
|
|
4698
|
+
//# sourceMappingURL=StudioUI-6CQ7MX7R.mjs.map
|