@gallop.software/studio 0.1.84 → 0.1.86
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-VNSW7JUI.js → StudioUI-PH265HCB.js} +170 -68
- package/dist/StudioUI-PH265HCB.js.map +1 -0
- package/dist/{StudioUI-EER6PAXH.mjs → StudioUI-QTKNMFLF.mjs} +166 -64
- package/dist/StudioUI-QTKNMFLF.mjs.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/StudioUI-EER6PAXH.mjs.map +0 -1
- package/dist/StudioUI-VNSW7JUI.js.map +0 -1
|
@@ -682,7 +682,8 @@ var ENV_TEMPLATE = `CLOUDFLARE_R2_ACCOUNT_ID=your_account_id
|
|
|
682
682
|
CLOUDFLARE_R2_ACCESS_KEY_ID=your_access_key
|
|
683
683
|
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_secret_key
|
|
684
684
|
CLOUDFLARE_R2_BUCKET_NAME=your_bucket_name
|
|
685
|
-
CLOUDFLARE_R2_PUBLIC_URL=https://pub-xxx.r2.dev
|
|
685
|
+
CLOUDFLARE_R2_PUBLIC_URL=https://pub-xxx.r2.dev
|
|
686
|
+
NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_URL=https://pub-xxx.r2.dev`;
|
|
686
687
|
var styles3 = {
|
|
687
688
|
overlay: _react3.css`
|
|
688
689
|
position: fixed;
|
|
@@ -1023,6 +1024,11 @@ function R2SetupModal({ isOpen, onClose }) {
|
|
|
1023
1024
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles3.envKey, children: "CLOUDFLARE_R2_PUBLIC_URL" }),
|
|
1024
1025
|
"=",
|
|
1025
1026
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles3.envValue, children: "https://pub-xxx.r2.dev" })
|
|
1027
|
+
] }),
|
|
1028
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles3.envVar, children: [
|
|
1029
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles3.envKey, children: "NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_URL" }),
|
|
1030
|
+
"=",
|
|
1031
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles3.envValue, children: "https://pub-xxx.r2.dev" })
|
|
1026
1032
|
] })
|
|
1027
1033
|
] }),
|
|
1028
1034
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { css: styles3.copyBtn, onClick: handleCopy, title: "Copy to clipboard", children: [
|
|
@@ -1288,39 +1294,92 @@ function StudioToolbar() {
|
|
|
1288
1294
|
const handleFileChange = _react.useCallback.call(void 0, async (e) => {
|
|
1289
1295
|
const files = e.target.files;
|
|
1290
1296
|
if (!files || files.length === 0) return;
|
|
1291
|
-
|
|
1297
|
+
const fileList = Array.from(files);
|
|
1298
|
+
if (fileList.length > 1) {
|
|
1299
|
+
setProgressState({
|
|
1300
|
+
current: 0,
|
|
1301
|
+
total: fileList.length,
|
|
1302
|
+
percent: 0,
|
|
1303
|
+
status: "processing",
|
|
1304
|
+
message: "Uploading files..."
|
|
1305
|
+
});
|
|
1306
|
+
setShowProgress(true);
|
|
1307
|
+
} else {
|
|
1308
|
+
setUploading(true);
|
|
1309
|
+
}
|
|
1310
|
+
let uploaded = 0;
|
|
1311
|
+
let errors = 0;
|
|
1292
1312
|
try {
|
|
1293
|
-
for (
|
|
1313
|
+
for (let i = 0; i < fileList.length; i++) {
|
|
1314
|
+
const file = fileList[i];
|
|
1315
|
+
if (fileList.length > 1) {
|
|
1316
|
+
setProgressState({
|
|
1317
|
+
current: i + 1,
|
|
1318
|
+
total: fileList.length,
|
|
1319
|
+
percent: Math.round((i + 1) / fileList.length * 100),
|
|
1320
|
+
status: "processing",
|
|
1321
|
+
currentFile: file.name
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1294
1324
|
const formData = new FormData();
|
|
1295
1325
|
formData.append("file", file);
|
|
1296
1326
|
formData.append("path", currentPath);
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1327
|
+
try {
|
|
1328
|
+
const response = await fetch("/api/studio/upload", {
|
|
1329
|
+
method: "POST",
|
|
1330
|
+
body: formData
|
|
1331
|
+
});
|
|
1332
|
+
if (!response.ok) {
|
|
1333
|
+
const error = await response.json();
|
|
1334
|
+
errors++;
|
|
1335
|
+
if (fileList.length === 1) {
|
|
1336
|
+
if (response.status >= 500) {
|
|
1337
|
+
console.error("Upload error:", error);
|
|
1338
|
+
setAlertMessage({
|
|
1339
|
+
title: "Upload Failed",
|
|
1340
|
+
message: `Failed to upload ${file.name}: ${error.error || "Unknown error"}`
|
|
1341
|
+
});
|
|
1342
|
+
} else {
|
|
1343
|
+
setAlertMessage({
|
|
1344
|
+
title: "Cannot Upload Here",
|
|
1345
|
+
message: error.error || "Upload not allowed in this location."
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1309
1349
|
} else {
|
|
1310
|
-
|
|
1311
|
-
title: "Cannot Upload Here",
|
|
1312
|
-
message: error.error || "Upload not allowed in this location."
|
|
1313
|
-
});
|
|
1350
|
+
uploaded++;
|
|
1314
1351
|
}
|
|
1352
|
+
} catch (e2) {
|
|
1353
|
+
errors++;
|
|
1315
1354
|
}
|
|
1316
1355
|
}
|
|
1356
|
+
if (fileList.length > 1) {
|
|
1357
|
+
setProgressState({
|
|
1358
|
+
current: fileList.length,
|
|
1359
|
+
total: fileList.length,
|
|
1360
|
+
percent: 100,
|
|
1361
|
+
status: "complete",
|
|
1362
|
+
processed: uploaded,
|
|
1363
|
+
errors
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1317
1366
|
triggerRefresh();
|
|
1318
1367
|
} catch (error) {
|
|
1319
1368
|
console.error("Upload error:", error);
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1369
|
+
if (fileList.length > 1) {
|
|
1370
|
+
setProgressState({
|
|
1371
|
+
current: 0,
|
|
1372
|
+
total: 0,
|
|
1373
|
+
percent: 0,
|
|
1374
|
+
status: "error",
|
|
1375
|
+
message: "Upload failed."
|
|
1376
|
+
});
|
|
1377
|
+
} else {
|
|
1378
|
+
setAlertMessage({
|
|
1379
|
+
title: "Upload Failed",
|
|
1380
|
+
message: "Upload failed. Check console for details."
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1324
1383
|
} finally {
|
|
1325
1384
|
setUploading(false);
|
|
1326
1385
|
if (fileInputRef.current) {
|
|
@@ -1461,7 +1520,7 @@ function StudioToolbar() {
|
|
|
1461
1520
|
message: data.message
|
|
1462
1521
|
}));
|
|
1463
1522
|
}
|
|
1464
|
-
} catch (
|
|
1523
|
+
} catch (e3) {
|
|
1465
1524
|
}
|
|
1466
1525
|
}
|
|
1467
1526
|
}
|
|
@@ -1574,56 +1633,99 @@ function StudioToolbar() {
|
|
|
1574
1633
|
}, [selectedItems, clearSelection, triggerRefresh]);
|
|
1575
1634
|
const handleSyncCdn = _react.useCallback.call(void 0, async () => {
|
|
1576
1635
|
if (selectedItems.size === 0) return;
|
|
1577
|
-
const
|
|
1636
|
+
const selectedPaths2 = Array.from(selectedItems);
|
|
1637
|
+
const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "svg", "ico", "bmp", "tiff", "tif"];
|
|
1638
|
+
const selectedImagePaths = selectedPaths2.filter((p) => {
|
|
1639
|
+
const ext = _optionalChain([p, 'access', _19 => _19.split, 'call', _20 => _20("."), 'access', _21 => _21.pop, 'call', _22 => _22(), 'optionalAccess', _23 => _23.toLowerCase, 'call', _24 => _24()]) || "";
|
|
1640
|
+
return imageExtensions.includes(ext);
|
|
1641
|
+
});
|
|
1642
|
+
const selectedFolders = selectedPaths2.filter((p) => !p.includes(".") || p.endsWith("/"));
|
|
1643
|
+
if (selectedFolders.length > 0) {
|
|
1644
|
+
try {
|
|
1645
|
+
const response = await fetch(`/api/studio/folder-images?folders=${encodeURIComponent(selectedFolders.join(","))}`);
|
|
1646
|
+
const data = await response.json();
|
|
1647
|
+
if (data.images) {
|
|
1648
|
+
for (const img of data.images) {
|
|
1649
|
+
const fullPath = `public/${img}`;
|
|
1650
|
+
if (!selectedImagePaths.includes(fullPath)) {
|
|
1651
|
+
selectedImagePaths.push(fullPath);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
} catch (error) {
|
|
1656
|
+
console.error("Failed to get folder images:", error);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
const imageKeys = selectedImagePaths.map((p) => "/" + p.replace(/^public\//, ""));
|
|
1578
1660
|
if (imageKeys.length === 0) {
|
|
1579
1661
|
setAlertMessage({
|
|
1580
|
-
title: "No Images
|
|
1581
|
-
message: "
|
|
1662
|
+
title: "No Images Found",
|
|
1663
|
+
message: "No images found in the selected items."
|
|
1582
1664
|
});
|
|
1583
1665
|
return;
|
|
1584
1666
|
}
|
|
1585
|
-
|
|
1667
|
+
setProgressState({
|
|
1668
|
+
current: 0,
|
|
1669
|
+
total: imageKeys.length,
|
|
1670
|
+
percent: 0,
|
|
1671
|
+
status: "processing",
|
|
1672
|
+
message: "Syncing to CDN..."
|
|
1673
|
+
});
|
|
1674
|
+
setShowProgress(true);
|
|
1675
|
+
let synced = 0;
|
|
1676
|
+
let errors = 0;
|
|
1586
1677
|
try {
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
} else {
|
|
1602
|
-
setAlertMessage({
|
|
1603
|
-
title: "Sync Complete",
|
|
1604
|
-
message: `Successfully synced ${syncedCount} images to CDN.`
|
|
1605
|
-
});
|
|
1606
|
-
}
|
|
1607
|
-
clearSelection();
|
|
1608
|
-
triggerRefresh();
|
|
1609
|
-
} else {
|
|
1610
|
-
if (_optionalChain([data, 'access', _23 => _23.error, 'optionalAccess', _24 => _24.includes, 'call', _25 => _25("R2 not configured")]) || _optionalChain([data, 'access', _26 => _26.error, 'optionalAccess', _27 => _27.includes, 'call', _28 => _28("CLOUDFLARE_R2")])) {
|
|
1611
|
-
setShowR2SetupModal(true);
|
|
1612
|
-
} else {
|
|
1613
|
-
setAlertMessage({
|
|
1614
|
-
title: "Sync Failed",
|
|
1615
|
-
message: data.error || "Failed to sync to CDN."
|
|
1678
|
+
for (let i = 0; i < imageKeys.length; i++) {
|
|
1679
|
+
const imageKey = imageKeys[i];
|
|
1680
|
+
setProgressState({
|
|
1681
|
+
current: i + 1,
|
|
1682
|
+
total: imageKeys.length,
|
|
1683
|
+
percent: Math.round((i + 1) / imageKeys.length * 100),
|
|
1684
|
+
status: "processing",
|
|
1685
|
+
currentFile: imageKey.replace(/^\//, "")
|
|
1686
|
+
});
|
|
1687
|
+
try {
|
|
1688
|
+
const response = await fetch("/api/studio/sync", {
|
|
1689
|
+
method: "POST",
|
|
1690
|
+
headers: { "Content-Type": "application/json" },
|
|
1691
|
+
body: JSON.stringify({ imageKeys: [imageKey] })
|
|
1616
1692
|
});
|
|
1693
|
+
const data = await response.json();
|
|
1694
|
+
if (!response.ok) {
|
|
1695
|
+
if (_optionalChain([data, 'access', _25 => _25.error, 'optionalAccess', _26 => _26.includes, 'call', _27 => _27("R2 not configured")]) || _optionalChain([data, 'access', _28 => _28.error, 'optionalAccess', _29 => _29.includes, 'call', _30 => _30("CLOUDFLARE_R2")])) {
|
|
1696
|
+
setShowProgress(false);
|
|
1697
|
+
setShowR2SetupModal(true);
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
errors++;
|
|
1701
|
+
} else if (_optionalChain([data, 'access', _31 => _31.synced, 'optionalAccess', _32 => _32.length]) > 0) {
|
|
1702
|
+
synced++;
|
|
1703
|
+
} else if (_optionalChain([data, 'access', _33 => _33.errors, 'optionalAccess', _34 => _34.length]) > 0) {
|
|
1704
|
+
errors++;
|
|
1705
|
+
}
|
|
1706
|
+
} catch (e4) {
|
|
1707
|
+
errors++;
|
|
1617
1708
|
}
|
|
1618
1709
|
}
|
|
1710
|
+
setProgressState({
|
|
1711
|
+
current: imageKeys.length,
|
|
1712
|
+
total: imageKeys.length,
|
|
1713
|
+
percent: 100,
|
|
1714
|
+
status: "complete",
|
|
1715
|
+
processed: synced,
|
|
1716
|
+
errors
|
|
1717
|
+
});
|
|
1718
|
+
clearSelection();
|
|
1719
|
+
triggerRefresh();
|
|
1619
1720
|
} catch (error) {
|
|
1620
1721
|
console.error("Sync error:", error);
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1722
|
+
setProgressState({
|
|
1723
|
+
current: 0,
|
|
1724
|
+
total: 0,
|
|
1725
|
+
percent: 0,
|
|
1726
|
+
status: "error",
|
|
1727
|
+
message: "Failed to sync to CDN."
|
|
1624
1728
|
});
|
|
1625
|
-
} finally {
|
|
1626
|
-
setSyncing(false);
|
|
1627
1729
|
}
|
|
1628
1730
|
}, [selectedItems, clearSelection, triggerRefresh]);
|
|
1629
1731
|
const handleCreateFolder = _react.useCallback.call(void 0, async (folderName) => {
|
|
@@ -1892,10 +1994,10 @@ function StudioToolbar() {
|
|
|
1892
1994
|
{
|
|
1893
1995
|
css: styles4.btn,
|
|
1894
1996
|
onClick: handleSyncCdn,
|
|
1895
|
-
disabled: !hasSelection
|
|
1997
|
+
disabled: !hasSelection,
|
|
1896
1998
|
children: [
|
|
1897
1999
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, CloudIcon, {}),
|
|
1898
|
-
|
|
2000
|
+
"Sync CDN"
|
|
1899
2001
|
]
|
|
1900
2002
|
}
|
|
1901
2003
|
),
|
|
@@ -3533,7 +3635,7 @@ function StudioDetailView() {
|
|
|
3533
3635
|
});
|
|
3534
3636
|
triggerRefresh();
|
|
3535
3637
|
} else {
|
|
3536
|
-
if (_optionalChain([data, 'access',
|
|
3638
|
+
if (_optionalChain([data, 'access', _35 => _35.error, 'optionalAccess', _36 => _36.includes, 'call', _37 => _37("R2 not configured")]) || _optionalChain([data, 'access', _38 => _38.error, 'optionalAccess', _39 => _39.includes, 'call', _40 => _40("CLOUDFLARE_R2")])) {
|
|
3537
3639
|
setShowR2SetupModal(true);
|
|
3538
3640
|
} else {
|
|
3539
3641
|
setAlertMessage({
|
|
@@ -3572,7 +3674,7 @@ function StudioDetailView() {
|
|
|
3572
3674
|
if (!response.ok) {
|
|
3573
3675
|
throw new Error("Processing failed");
|
|
3574
3676
|
}
|
|
3575
|
-
const reader = _optionalChain([response, 'access',
|
|
3677
|
+
const reader = _optionalChain([response, 'access', _41 => _41.body, 'optionalAccess', _42 => _42.getReader, 'call', _43 => _43()]);
|
|
3576
3678
|
if (!reader) {
|
|
3577
3679
|
throw new Error("No response body");
|
|
3578
3680
|
}
|
|
@@ -3589,7 +3691,7 @@ function StudioDetailView() {
|
|
|
3589
3691
|
try {
|
|
3590
3692
|
const data = JSON.parse(line.slice(6));
|
|
3591
3693
|
setProcessProgress(data);
|
|
3592
|
-
} catch (
|
|
3694
|
+
} catch (e5) {
|
|
3593
3695
|
}
|
|
3594
3696
|
}
|
|
3595
3697
|
}
|
|
@@ -4519,4 +4621,4 @@ var StudioUI_default = StudioUI;
|
|
|
4519
4621
|
|
|
4520
4622
|
|
|
4521
4623
|
exports.StudioUI = StudioUI; exports.default = StudioUI_default;
|
|
4522
|
-
//# sourceMappingURL=StudioUI-
|
|
4624
|
+
//# sourceMappingURL=StudioUI-PH265HCB.js.map
|