@weirdfingers/boards 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +23 -9
- package/dist/index.d.ts +23 -9
- package/dist/index.js +191 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +190 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
- package/src/graphql/operations.ts +6 -0
- package/src/hooks/__tests__/useMultiUpload.test.ts +238 -0
- package/src/hooks/useGeneration.ts +44 -0
- package/src/hooks/useMultiUpload.ts +309 -0
- package/src/index.ts +7 -5
- package/src/hooks/useUpload.ts +0 -175
package/dist/index.mjs
CHANGED
|
@@ -815,6 +815,11 @@ var RETRY_GENERATION = gql`
|
|
|
815
815
|
}
|
|
816
816
|
}
|
|
817
817
|
`;
|
|
818
|
+
var DELETE_GENERATION = gql`
|
|
819
|
+
mutation DeleteGeneration($id: UUID!) {
|
|
820
|
+
deleteGeneration(id: $id)
|
|
821
|
+
}
|
|
822
|
+
`;
|
|
818
823
|
var UPLOAD_ARTIFACT_FROM_URL = gql`
|
|
819
824
|
${GENERATION_FRAGMENT}
|
|
820
825
|
mutation UploadArtifactFromUrl($input: UploadArtifactInput!) {
|
|
@@ -1103,6 +1108,7 @@ function useGeneration() {
|
|
|
1103
1108
|
const [, createGenerationMutation] = useMutation3(CREATE_GENERATION);
|
|
1104
1109
|
const [, cancelGenerationMutation] = useMutation3(CANCEL_GENERATION);
|
|
1105
1110
|
const [, retryGenerationMutation] = useMutation3(RETRY_GENERATION);
|
|
1111
|
+
const [, deleteGenerationMutation] = useMutation3(DELETE_GENERATION);
|
|
1106
1112
|
useEffect2(() => {
|
|
1107
1113
|
return () => {
|
|
1108
1114
|
abortControllers.current.forEach((controller) => {
|
|
@@ -1312,6 +1318,36 @@ function useGeneration() {
|
|
|
1312
1318
|
},
|
|
1313
1319
|
[retryGenerationMutation, connectToSSE]
|
|
1314
1320
|
);
|
|
1321
|
+
const deleteGeneration = useCallback5(
|
|
1322
|
+
async (jobId) => {
|
|
1323
|
+
try {
|
|
1324
|
+
const result2 = await deleteGenerationMutation({ id: jobId });
|
|
1325
|
+
if (result2.error) {
|
|
1326
|
+
throw new Error(result2.error.message);
|
|
1327
|
+
}
|
|
1328
|
+
if (!result2.data?.deleteGeneration) {
|
|
1329
|
+
throw new Error("Failed to delete generation");
|
|
1330
|
+
}
|
|
1331
|
+
const controller = abortControllers.current.get(jobId);
|
|
1332
|
+
if (controller) {
|
|
1333
|
+
controller.abort();
|
|
1334
|
+
abortControllers.current.delete(jobId);
|
|
1335
|
+
}
|
|
1336
|
+
if (progress?.jobId === jobId) {
|
|
1337
|
+
setProgress(null);
|
|
1338
|
+
setResult(null);
|
|
1339
|
+
setIsGenerating(false);
|
|
1340
|
+
}
|
|
1341
|
+
setHistory((prev) => prev.filter((item) => item.jobId !== jobId));
|
|
1342
|
+
} catch (err) {
|
|
1343
|
+
setError(
|
|
1344
|
+
err instanceof Error ? err : new Error("Failed to delete generation")
|
|
1345
|
+
);
|
|
1346
|
+
throw err;
|
|
1347
|
+
}
|
|
1348
|
+
},
|
|
1349
|
+
[deleteGenerationMutation, progress]
|
|
1350
|
+
);
|
|
1315
1351
|
const clearHistory = useCallback5(() => {
|
|
1316
1352
|
setHistory([]);
|
|
1317
1353
|
}, []);
|
|
@@ -1323,6 +1359,7 @@ function useGeneration() {
|
|
|
1323
1359
|
submit,
|
|
1324
1360
|
cancel,
|
|
1325
1361
|
retry,
|
|
1362
|
+
deleteGeneration,
|
|
1326
1363
|
history,
|
|
1327
1364
|
clearHistory
|
|
1328
1365
|
};
|
|
@@ -1345,21 +1382,44 @@ function useGenerators(options = {}) {
|
|
|
1345
1382
|
};
|
|
1346
1383
|
}
|
|
1347
1384
|
|
|
1348
|
-
// src/hooks/
|
|
1349
|
-
import { useCallback as useCallback6, useState as useState5 } from "react";
|
|
1385
|
+
// src/hooks/useMultiUpload.ts
|
|
1386
|
+
import { useCallback as useCallback6, useState as useState5, useRef as useRef2 } from "react";
|
|
1350
1387
|
import { useMutation as useMutation4 } from "urql";
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1388
|
+
var uploadIdCounter = 0;
|
|
1389
|
+
function generateUploadId() {
|
|
1390
|
+
return `upload-${Date.now()}-${++uploadIdCounter}`;
|
|
1391
|
+
}
|
|
1392
|
+
function getFileName(source) {
|
|
1393
|
+
if (typeof source === "string") {
|
|
1394
|
+
try {
|
|
1395
|
+
const url = new URL(source);
|
|
1396
|
+
const pathParts = url.pathname.split("/");
|
|
1397
|
+
return pathParts[pathParts.length - 1] || source;
|
|
1398
|
+
} catch {
|
|
1399
|
+
return source;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
return source.name;
|
|
1403
|
+
}
|
|
1404
|
+
function useMultiUpload() {
|
|
1405
|
+
const [uploads, setUploads] = useState5([]);
|
|
1406
|
+
const abortControllersRef = useRef2(/* @__PURE__ */ new Map());
|
|
1355
1407
|
const { apiUrl } = useApiConfig();
|
|
1356
1408
|
const auth = useAuth();
|
|
1357
1409
|
const [, uploadFromUrlMutation] = useMutation4(UPLOAD_ARTIFACT_FROM_URL);
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1410
|
+
const updateUpload = useCallback6(
|
|
1411
|
+
(uploadId, updates) => {
|
|
1412
|
+
setUploads(
|
|
1413
|
+
(prev) => prev.map(
|
|
1414
|
+
(item) => item.id === uploadId ? { ...item, ...updates } : item
|
|
1415
|
+
)
|
|
1416
|
+
);
|
|
1417
|
+
},
|
|
1418
|
+
[]
|
|
1419
|
+
);
|
|
1420
|
+
const uploadSingle = useCallback6(
|
|
1421
|
+
async (uploadId, request) => {
|
|
1422
|
+
updateUpload(uploadId, { status: "uploading", progress: 0 });
|
|
1363
1423
|
try {
|
|
1364
1424
|
if (typeof request.source === "string") {
|
|
1365
1425
|
const result2 = await uploadFromUrlMutation({
|
|
@@ -1377,9 +1437,7 @@ function useUpload() {
|
|
|
1377
1437
|
if (!result2.data?.uploadArtifact) {
|
|
1378
1438
|
throw new Error("Upload failed");
|
|
1379
1439
|
}
|
|
1380
|
-
|
|
1381
|
-
setIsUploading(false);
|
|
1382
|
-
return {
|
|
1440
|
+
const uploadResult = {
|
|
1383
1441
|
id: result2.data.uploadArtifact.id,
|
|
1384
1442
|
storageUrl: result2.data.uploadArtifact.storageUrl,
|
|
1385
1443
|
thumbnailUrl: result2.data.uploadArtifact.thumbnailUrl,
|
|
@@ -1387,6 +1445,12 @@ function useUpload() {
|
|
|
1387
1445
|
artifactType: result2.data.uploadArtifact.artifactType,
|
|
1388
1446
|
generatorName: result2.data.uploadArtifact.generatorName
|
|
1389
1447
|
};
|
|
1448
|
+
updateUpload(uploadId, {
|
|
1449
|
+
status: "completed",
|
|
1450
|
+
progress: 100,
|
|
1451
|
+
result: uploadResult
|
|
1452
|
+
});
|
|
1453
|
+
return uploadResult;
|
|
1390
1454
|
}
|
|
1391
1455
|
const formData = new FormData();
|
|
1392
1456
|
formData.append("board_id", request.boardId);
|
|
@@ -1403,68 +1467,128 @@ function useUpload() {
|
|
|
1403
1467
|
if (token) {
|
|
1404
1468
|
headers.Authorization = `Bearer ${token}`;
|
|
1405
1469
|
}
|
|
1406
|
-
const result = await new Promise(
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
const data = JSON.parse(xhr.responseText);
|
|
1418
|
-
resolve({
|
|
1419
|
-
id: data.id,
|
|
1420
|
-
storageUrl: data.storageUrl,
|
|
1421
|
-
thumbnailUrl: data.thumbnailUrl,
|
|
1422
|
-
status: "completed",
|
|
1423
|
-
artifactType: data.artifactType,
|
|
1424
|
-
generatorName: data.generatorName
|
|
1425
|
-
});
|
|
1426
|
-
} catch (err) {
|
|
1427
|
-
reject(new Error("Failed to parse response"));
|
|
1470
|
+
const result = await new Promise(
|
|
1471
|
+
(resolve, reject) => {
|
|
1472
|
+
const xhr = new XMLHttpRequest();
|
|
1473
|
+
abortControllersRef.current.set(uploadId, () => xhr.abort());
|
|
1474
|
+
const cleanup = () => {
|
|
1475
|
+
abortControllersRef.current.delete(uploadId);
|
|
1476
|
+
};
|
|
1477
|
+
xhr.upload.addEventListener("progress", (e) => {
|
|
1478
|
+
if (e.lengthComputable) {
|
|
1479
|
+
const percentComplete = e.loaded / e.total * 100;
|
|
1480
|
+
updateUpload(uploadId, { progress: percentComplete });
|
|
1428
1481
|
}
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1482
|
+
});
|
|
1483
|
+
xhr.addEventListener("load", () => {
|
|
1484
|
+
cleanup();
|
|
1485
|
+
if (xhr.status === 200) {
|
|
1486
|
+
try {
|
|
1487
|
+
const data = JSON.parse(xhr.responseText);
|
|
1488
|
+
resolve({
|
|
1489
|
+
id: data.id,
|
|
1490
|
+
storageUrl: data.storageUrl,
|
|
1491
|
+
thumbnailUrl: data.thumbnailUrl,
|
|
1492
|
+
status: "completed",
|
|
1493
|
+
artifactType: data.artifactType,
|
|
1494
|
+
generatorName: data.generatorName
|
|
1495
|
+
});
|
|
1496
|
+
} catch (err) {
|
|
1497
|
+
reject(new Error("Failed to parse response"));
|
|
1498
|
+
}
|
|
1499
|
+
} else {
|
|
1500
|
+
try {
|
|
1501
|
+
const errorData = JSON.parse(xhr.responseText);
|
|
1502
|
+
reject(
|
|
1503
|
+
new Error(
|
|
1504
|
+
errorData.detail || `Upload failed: ${xhr.statusText}`
|
|
1505
|
+
)
|
|
1506
|
+
);
|
|
1507
|
+
} catch {
|
|
1508
|
+
reject(new Error(`Upload failed: ${xhr.statusText}`));
|
|
1509
|
+
}
|
|
1435
1510
|
}
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1511
|
+
});
|
|
1512
|
+
xhr.addEventListener("error", () => {
|
|
1513
|
+
cleanup();
|
|
1514
|
+
reject(new Error("Upload failed: Network error"));
|
|
1515
|
+
});
|
|
1516
|
+
xhr.addEventListener("abort", () => {
|
|
1517
|
+
cleanup();
|
|
1518
|
+
reject(new Error("Upload cancelled"));
|
|
1519
|
+
});
|
|
1520
|
+
xhr.addEventListener("loadend", () => {
|
|
1521
|
+
cleanup();
|
|
1522
|
+
});
|
|
1523
|
+
xhr.open("POST", `${apiUrl}/api/uploads/artifact`);
|
|
1524
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
1525
|
+
xhr.setRequestHeader(key, value);
|
|
1526
|
+
});
|
|
1527
|
+
xhr.send(formData);
|
|
1528
|
+
}
|
|
1529
|
+
);
|
|
1530
|
+
updateUpload(uploadId, {
|
|
1531
|
+
status: "completed",
|
|
1532
|
+
progress: 100,
|
|
1533
|
+
result
|
|
1449
1534
|
});
|
|
1450
|
-
setProgress(100);
|
|
1451
|
-
setIsUploading(false);
|
|
1452
1535
|
return result;
|
|
1453
1536
|
} catch (err) {
|
|
1454
1537
|
const uploadError = err instanceof Error ? err : new Error("Upload failed");
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1538
|
+
updateUpload(uploadId, {
|
|
1539
|
+
status: "failed",
|
|
1540
|
+
error: uploadError
|
|
1541
|
+
});
|
|
1458
1542
|
throw uploadError;
|
|
1459
1543
|
}
|
|
1460
1544
|
},
|
|
1461
|
-
[uploadFromUrlMutation, apiUrl, auth]
|
|
1545
|
+
[uploadFromUrlMutation, apiUrl, auth, updateUpload]
|
|
1462
1546
|
);
|
|
1547
|
+
const uploadMultiple = useCallback6(
|
|
1548
|
+
async (requests) => {
|
|
1549
|
+
const newUploads = requests.map((request) => ({
|
|
1550
|
+
id: generateUploadId(),
|
|
1551
|
+
file: request.source,
|
|
1552
|
+
fileName: getFileName(request.source),
|
|
1553
|
+
status: "pending",
|
|
1554
|
+
progress: 0
|
|
1555
|
+
}));
|
|
1556
|
+
setUploads((prev) => [...prev, ...newUploads]);
|
|
1557
|
+
const results = await Promise.allSettled(
|
|
1558
|
+
requests.map(
|
|
1559
|
+
(request, index) => uploadSingle(newUploads[index].id, request)
|
|
1560
|
+
)
|
|
1561
|
+
);
|
|
1562
|
+
const successfulResults = [];
|
|
1563
|
+
results.forEach((result) => {
|
|
1564
|
+
if (result.status === "fulfilled") {
|
|
1565
|
+
successfulResults.push(result.value);
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
return successfulResults;
|
|
1569
|
+
},
|
|
1570
|
+
[uploadSingle]
|
|
1571
|
+
);
|
|
1572
|
+
const clearUploads = useCallback6(() => {
|
|
1573
|
+
abortControllersRef.current.forEach((abort) => abort());
|
|
1574
|
+
abortControllersRef.current.clear();
|
|
1575
|
+
setUploads([]);
|
|
1576
|
+
}, []);
|
|
1577
|
+
const cancelUpload = useCallback6((uploadId) => {
|
|
1578
|
+
const abort = abortControllersRef.current.get(uploadId);
|
|
1579
|
+
if (abort) {
|
|
1580
|
+
abort();
|
|
1581
|
+
}
|
|
1582
|
+
}, []);
|
|
1583
|
+
const isUploading = uploads.some((u) => u.status === "uploading");
|
|
1584
|
+
const overallProgress = uploads.length > 0 ? uploads.reduce((sum, u) => sum + u.progress, 0) / uploads.length : 0;
|
|
1463
1585
|
return {
|
|
1464
|
-
|
|
1586
|
+
uploadMultiple,
|
|
1587
|
+
uploads,
|
|
1465
1588
|
isUploading,
|
|
1466
|
-
|
|
1467
|
-
|
|
1589
|
+
overallProgress,
|
|
1590
|
+
clearUploads,
|
|
1591
|
+
cancelUpload
|
|
1468
1592
|
};
|
|
1469
1593
|
}
|
|
1470
1594
|
|
|
@@ -1581,6 +1705,7 @@ export {
|
|
|
1581
1705
|
CREATE_BOARD,
|
|
1582
1706
|
CREATE_GENERATION,
|
|
1583
1707
|
DELETE_BOARD,
|
|
1708
|
+
DELETE_GENERATION,
|
|
1584
1709
|
DESCENDANT_NODE_FRAGMENT,
|
|
1585
1710
|
GENERATION_FRAGMENT,
|
|
1586
1711
|
GET_ANCESTRY,
|
|
@@ -1620,6 +1745,6 @@ export {
|
|
|
1620
1745
|
useGenerators,
|
|
1621
1746
|
useInputArtifacts,
|
|
1622
1747
|
useLineage,
|
|
1623
|
-
|
|
1748
|
+
useMultiUpload
|
|
1624
1749
|
};
|
|
1625
1750
|
//# sourceMappingURL=index.mjs.map
|