@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.d.mts
CHANGED
|
@@ -389,6 +389,7 @@ declare const REMOVE_BOARD_MEMBER: urql.TypedDocumentNode<any, urql.AnyVariables
|
|
|
389
389
|
declare const CREATE_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
390
390
|
declare const CANCEL_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
391
391
|
declare const RETRY_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
392
|
+
declare const DELETE_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
392
393
|
declare const UPLOAD_ARTIFACT_FROM_URL: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
393
394
|
interface CreateBoardInput {
|
|
394
395
|
title: string;
|
|
@@ -652,6 +653,7 @@ interface GenerationHook {
|
|
|
652
653
|
submit: (request: GenerationRequest) => Promise<string>;
|
|
653
654
|
cancel: (jobId: string) => Promise<void>;
|
|
654
655
|
retry: (jobId: string) => Promise<void>;
|
|
656
|
+
deleteGeneration: (jobId: string) => Promise<void>;
|
|
655
657
|
history: GenerationResult[];
|
|
656
658
|
clearHistory: () => void;
|
|
657
659
|
}
|
|
@@ -679,17 +681,17 @@ interface GeneratorsHook {
|
|
|
679
681
|
declare function useGenerators(options?: UseGeneratorsOptions): GeneratorsHook;
|
|
680
682
|
|
|
681
683
|
/**
|
|
682
|
-
* Hook for uploading artifacts
|
|
684
|
+
* Hook for uploading multiple artifacts concurrently with individual progress tracking.
|
|
683
685
|
*/
|
|
684
686
|
|
|
685
|
-
interface
|
|
687
|
+
interface MultiUploadRequest {
|
|
686
688
|
boardId: string;
|
|
687
689
|
artifactType: ArtifactType;
|
|
688
690
|
source: File | string;
|
|
689
691
|
userDescription?: string;
|
|
690
692
|
parentGenerationId?: string;
|
|
691
693
|
}
|
|
692
|
-
interface
|
|
694
|
+
interface MultiUploadResult {
|
|
693
695
|
id: string;
|
|
694
696
|
storageUrl: string;
|
|
695
697
|
thumbnailUrl?: string;
|
|
@@ -697,13 +699,25 @@ interface UploadResult {
|
|
|
697
699
|
artifactType: ArtifactType;
|
|
698
700
|
generatorName: string;
|
|
699
701
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
702
|
+
type UploadStatus = "pending" | "uploading" | "completed" | "failed";
|
|
703
|
+
interface UploadItem {
|
|
704
|
+
id: string;
|
|
705
|
+
file: File | string;
|
|
706
|
+
fileName: string;
|
|
707
|
+
status: UploadStatus;
|
|
703
708
|
progress: number;
|
|
704
|
-
|
|
709
|
+
result?: MultiUploadResult;
|
|
710
|
+
error?: Error;
|
|
711
|
+
}
|
|
712
|
+
interface MultiUploadHook {
|
|
713
|
+
uploadMultiple: (requests: MultiUploadRequest[]) => Promise<MultiUploadResult[]>;
|
|
714
|
+
uploads: UploadItem[];
|
|
715
|
+
isUploading: boolean;
|
|
716
|
+
overallProgress: number;
|
|
717
|
+
clearUploads: () => void;
|
|
718
|
+
cancelUpload: (uploadId: string) => void;
|
|
705
719
|
}
|
|
706
|
-
declare function
|
|
720
|
+
declare function useMultiUpload(): MultiUploadHook;
|
|
707
721
|
|
|
708
722
|
/**
|
|
709
723
|
* Hook for accessing generation lineage (ancestry and descendants).
|
|
@@ -908,4 +922,4 @@ declare function BoardsProvider({ children, apiUrl, graphqlUrl, subscriptionUrl,
|
|
|
908
922
|
|
|
909
923
|
declare const VERSION = "0.1.0";
|
|
910
924
|
|
|
911
|
-
export { ADD_BOARD_MEMBER, ANCESTRY_NODE_FRAGMENT, ARTIFACT_LINEAGE_FRAGMENT, type AncestryNode, type ApiConfig, type Artifact$1 as Artifact, type ArtifactLineage, type ArtifactSlot, type ArtifactSlotInfo, ArtifactType, type AuthContextValue, AuthProvider, type AuthProviderConfig, type AuthState$1 as AuthState, BOARD_FRAGMENT, BaseAuthProvider, BoardRole, BoardsProvider, CANCEL_GENERATION, CREATE_BOARD, CREATE_GENERATION, type CreateBoardInput, type CreateGenerationInput, DELETE_BOARD, DESCENDANT_NODE_FRAGMENT, type DescendantNode, type DropdownField, GENERATION_FRAGMENT, GET_ANCESTRY, GET_BOARD, GET_BOARDS, GET_CURRENT_USER, GET_DESCENDANTS, GET_GENERATION, GET_GENERATIONS, GET_GENERATORS, GET_INPUT_ARTIFACTS, GenerationStatus, type Generator, type GeneratorInfo, type GeneratorSelectionContextValue, GeneratorSelectionProvider, NoAuthProvider, type NumberInputField, type ParsedGeneratorSchema, type PromptField, REMOVE_BOARD_MEMBER, RETRY_GENERATION, type SettingsField, type SignInOptions, type SliderField, type TextInputField, UPDATE_BOARD, UPDATE_BOARD_MEMBER_ROLE, UPLOAD_ARTIFACT_FROM_URL, USER_FRAGMENT, type UpdateBoardInput, type UploadArtifactInput, type
|
|
925
|
+
export { ADD_BOARD_MEMBER, ANCESTRY_NODE_FRAGMENT, ARTIFACT_LINEAGE_FRAGMENT, type AncestryNode, type ApiConfig, type Artifact$1 as Artifact, type ArtifactLineage, type ArtifactSlot, type ArtifactSlotInfo, ArtifactType, type AuthContextValue, AuthProvider, type AuthProviderConfig, type AuthState$1 as AuthState, BOARD_FRAGMENT, BaseAuthProvider, BoardRole, BoardsProvider, CANCEL_GENERATION, CREATE_BOARD, CREATE_GENERATION, type CreateBoardInput, type CreateGenerationInput, DELETE_BOARD, DELETE_GENERATION, DESCENDANT_NODE_FRAGMENT, type DescendantNode, type DropdownField, GENERATION_FRAGMENT, GET_ANCESTRY, GET_BOARD, GET_BOARDS, GET_CURRENT_USER, GET_DESCENDANTS, GET_GENERATION, GET_GENERATIONS, GET_GENERATORS, GET_INPUT_ARTIFACTS, GenerationStatus, type Generator, type GeneratorInfo, type GeneratorSelectionContextValue, GeneratorSelectionProvider, type MultiUploadHook, type MultiUploadRequest, type MultiUploadResult, NoAuthProvider, type NumberInputField, type ParsedGeneratorSchema, type PromptField, REMOVE_BOARD_MEMBER, RETRY_GENERATION, type SettingsField, type SignInOptions, type SliderField, type TextInputField, UPDATE_BOARD, UPDATE_BOARD_MEMBER_ROLE, UPLOAD_ARTIFACT_FROM_URL, USER_FRAGMENT, type UpdateBoardInput, type UploadArtifactInput, type UploadItem, type UploadStatus, type User$1 as User, VERSION, createGraphQLClient, getArtifactType, isArtifactReference, parseArtifactSlot, parseGeneratorSchema, parseSettingsField, useAncestry, useApiConfig, useAuth, useAuthOptional, useBoard, useBoards, useDescendants, useGeneration, useGeneratorSelection, useGenerators, useInputArtifacts, useLineage, useMultiUpload };
|
package/dist/index.d.ts
CHANGED
|
@@ -389,6 +389,7 @@ declare const REMOVE_BOARD_MEMBER: urql.TypedDocumentNode<any, urql.AnyVariables
|
|
|
389
389
|
declare const CREATE_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
390
390
|
declare const CANCEL_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
391
391
|
declare const RETRY_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
392
|
+
declare const DELETE_GENERATION: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
392
393
|
declare const UPLOAD_ARTIFACT_FROM_URL: urql.TypedDocumentNode<any, urql.AnyVariables>;
|
|
393
394
|
interface CreateBoardInput {
|
|
394
395
|
title: string;
|
|
@@ -652,6 +653,7 @@ interface GenerationHook {
|
|
|
652
653
|
submit: (request: GenerationRequest) => Promise<string>;
|
|
653
654
|
cancel: (jobId: string) => Promise<void>;
|
|
654
655
|
retry: (jobId: string) => Promise<void>;
|
|
656
|
+
deleteGeneration: (jobId: string) => Promise<void>;
|
|
655
657
|
history: GenerationResult[];
|
|
656
658
|
clearHistory: () => void;
|
|
657
659
|
}
|
|
@@ -679,17 +681,17 @@ interface GeneratorsHook {
|
|
|
679
681
|
declare function useGenerators(options?: UseGeneratorsOptions): GeneratorsHook;
|
|
680
682
|
|
|
681
683
|
/**
|
|
682
|
-
* Hook for uploading artifacts
|
|
684
|
+
* Hook for uploading multiple artifacts concurrently with individual progress tracking.
|
|
683
685
|
*/
|
|
684
686
|
|
|
685
|
-
interface
|
|
687
|
+
interface MultiUploadRequest {
|
|
686
688
|
boardId: string;
|
|
687
689
|
artifactType: ArtifactType;
|
|
688
690
|
source: File | string;
|
|
689
691
|
userDescription?: string;
|
|
690
692
|
parentGenerationId?: string;
|
|
691
693
|
}
|
|
692
|
-
interface
|
|
694
|
+
interface MultiUploadResult {
|
|
693
695
|
id: string;
|
|
694
696
|
storageUrl: string;
|
|
695
697
|
thumbnailUrl?: string;
|
|
@@ -697,13 +699,25 @@ interface UploadResult {
|
|
|
697
699
|
artifactType: ArtifactType;
|
|
698
700
|
generatorName: string;
|
|
699
701
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
702
|
+
type UploadStatus = "pending" | "uploading" | "completed" | "failed";
|
|
703
|
+
interface UploadItem {
|
|
704
|
+
id: string;
|
|
705
|
+
file: File | string;
|
|
706
|
+
fileName: string;
|
|
707
|
+
status: UploadStatus;
|
|
703
708
|
progress: number;
|
|
704
|
-
|
|
709
|
+
result?: MultiUploadResult;
|
|
710
|
+
error?: Error;
|
|
711
|
+
}
|
|
712
|
+
interface MultiUploadHook {
|
|
713
|
+
uploadMultiple: (requests: MultiUploadRequest[]) => Promise<MultiUploadResult[]>;
|
|
714
|
+
uploads: UploadItem[];
|
|
715
|
+
isUploading: boolean;
|
|
716
|
+
overallProgress: number;
|
|
717
|
+
clearUploads: () => void;
|
|
718
|
+
cancelUpload: (uploadId: string) => void;
|
|
705
719
|
}
|
|
706
|
-
declare function
|
|
720
|
+
declare function useMultiUpload(): MultiUploadHook;
|
|
707
721
|
|
|
708
722
|
/**
|
|
709
723
|
* Hook for accessing generation lineage (ancestry and descendants).
|
|
@@ -908,4 +922,4 @@ declare function BoardsProvider({ children, apiUrl, graphqlUrl, subscriptionUrl,
|
|
|
908
922
|
|
|
909
923
|
declare const VERSION = "0.1.0";
|
|
910
924
|
|
|
911
|
-
export { ADD_BOARD_MEMBER, ANCESTRY_NODE_FRAGMENT, ARTIFACT_LINEAGE_FRAGMENT, type AncestryNode, type ApiConfig, type Artifact$1 as Artifact, type ArtifactLineage, type ArtifactSlot, type ArtifactSlotInfo, ArtifactType, type AuthContextValue, AuthProvider, type AuthProviderConfig, type AuthState$1 as AuthState, BOARD_FRAGMENT, BaseAuthProvider, BoardRole, BoardsProvider, CANCEL_GENERATION, CREATE_BOARD, CREATE_GENERATION, type CreateBoardInput, type CreateGenerationInput, DELETE_BOARD, DESCENDANT_NODE_FRAGMENT, type DescendantNode, type DropdownField, GENERATION_FRAGMENT, GET_ANCESTRY, GET_BOARD, GET_BOARDS, GET_CURRENT_USER, GET_DESCENDANTS, GET_GENERATION, GET_GENERATIONS, GET_GENERATORS, GET_INPUT_ARTIFACTS, GenerationStatus, type Generator, type GeneratorInfo, type GeneratorSelectionContextValue, GeneratorSelectionProvider, NoAuthProvider, type NumberInputField, type ParsedGeneratorSchema, type PromptField, REMOVE_BOARD_MEMBER, RETRY_GENERATION, type SettingsField, type SignInOptions, type SliderField, type TextInputField, UPDATE_BOARD, UPDATE_BOARD_MEMBER_ROLE, UPLOAD_ARTIFACT_FROM_URL, USER_FRAGMENT, type UpdateBoardInput, type UploadArtifactInput, type
|
|
925
|
+
export { ADD_BOARD_MEMBER, ANCESTRY_NODE_FRAGMENT, ARTIFACT_LINEAGE_FRAGMENT, type AncestryNode, type ApiConfig, type Artifact$1 as Artifact, type ArtifactLineage, type ArtifactSlot, type ArtifactSlotInfo, ArtifactType, type AuthContextValue, AuthProvider, type AuthProviderConfig, type AuthState$1 as AuthState, BOARD_FRAGMENT, BaseAuthProvider, BoardRole, BoardsProvider, CANCEL_GENERATION, CREATE_BOARD, CREATE_GENERATION, type CreateBoardInput, type CreateGenerationInput, DELETE_BOARD, DELETE_GENERATION, DESCENDANT_NODE_FRAGMENT, type DescendantNode, type DropdownField, GENERATION_FRAGMENT, GET_ANCESTRY, GET_BOARD, GET_BOARDS, GET_CURRENT_USER, GET_DESCENDANTS, GET_GENERATION, GET_GENERATIONS, GET_GENERATORS, GET_INPUT_ARTIFACTS, GenerationStatus, type Generator, type GeneratorInfo, type GeneratorSelectionContextValue, GeneratorSelectionProvider, type MultiUploadHook, type MultiUploadRequest, type MultiUploadResult, NoAuthProvider, type NumberInputField, type ParsedGeneratorSchema, type PromptField, REMOVE_BOARD_MEMBER, RETRY_GENERATION, type SettingsField, type SignInOptions, type SliderField, type TextInputField, UPDATE_BOARD, UPDATE_BOARD_MEMBER_ROLE, UPLOAD_ARTIFACT_FROM_URL, USER_FRAGMENT, type UpdateBoardInput, type UploadArtifactInput, type UploadItem, type UploadStatus, type User$1 as User, VERSION, createGraphQLClient, getArtifactType, isArtifactReference, parseArtifactSlot, parseGeneratorSchema, parseSettingsField, useAncestry, useApiConfig, useAuth, useAuthOptional, useBoard, useBoards, useDescendants, useGeneration, useGeneratorSelection, useGenerators, useInputArtifacts, useLineage, useMultiUpload };
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
CREATE_BOARD: () => CREATE_BOARD,
|
|
34
34
|
CREATE_GENERATION: () => CREATE_GENERATION,
|
|
35
35
|
DELETE_BOARD: () => DELETE_BOARD,
|
|
36
|
+
DELETE_GENERATION: () => DELETE_GENERATION,
|
|
36
37
|
DESCENDANT_NODE_FRAGMENT: () => DESCENDANT_NODE_FRAGMENT,
|
|
37
38
|
GENERATION_FRAGMENT: () => GENERATION_FRAGMENT,
|
|
38
39
|
GET_ANCESTRY: () => GET_ANCESTRY,
|
|
@@ -72,7 +73,7 @@ __export(index_exports, {
|
|
|
72
73
|
useGenerators: () => useGenerators,
|
|
73
74
|
useInputArtifacts: () => useInputArtifacts,
|
|
74
75
|
useLineage: () => useLineage,
|
|
75
|
-
|
|
76
|
+
useMultiUpload: () => useMultiUpload
|
|
76
77
|
});
|
|
77
78
|
module.exports = __toCommonJS(index_exports);
|
|
78
79
|
|
|
@@ -887,6 +888,11 @@ var RETRY_GENERATION = import_urql2.gql`
|
|
|
887
888
|
}
|
|
888
889
|
}
|
|
889
890
|
`;
|
|
891
|
+
var DELETE_GENERATION = import_urql2.gql`
|
|
892
|
+
mutation DeleteGeneration($id: UUID!) {
|
|
893
|
+
deleteGeneration(id: $id)
|
|
894
|
+
}
|
|
895
|
+
`;
|
|
890
896
|
var UPLOAD_ARTIFACT_FROM_URL = import_urql2.gql`
|
|
891
897
|
${GENERATION_FRAGMENT}
|
|
892
898
|
mutation UploadArtifactFromUrl($input: UploadArtifactInput!) {
|
|
@@ -1175,6 +1181,7 @@ function useGeneration() {
|
|
|
1175
1181
|
const [, createGenerationMutation] = (0, import_urql5.useMutation)(CREATE_GENERATION);
|
|
1176
1182
|
const [, cancelGenerationMutation] = (0, import_urql5.useMutation)(CANCEL_GENERATION);
|
|
1177
1183
|
const [, retryGenerationMutation] = (0, import_urql5.useMutation)(RETRY_GENERATION);
|
|
1184
|
+
const [, deleteGenerationMutation] = (0, import_urql5.useMutation)(DELETE_GENERATION);
|
|
1178
1185
|
(0, import_react6.useEffect)(() => {
|
|
1179
1186
|
return () => {
|
|
1180
1187
|
abortControllers.current.forEach((controller) => {
|
|
@@ -1384,6 +1391,36 @@ function useGeneration() {
|
|
|
1384
1391
|
},
|
|
1385
1392
|
[retryGenerationMutation, connectToSSE]
|
|
1386
1393
|
);
|
|
1394
|
+
const deleteGeneration = (0, import_react6.useCallback)(
|
|
1395
|
+
async (jobId) => {
|
|
1396
|
+
try {
|
|
1397
|
+
const result2 = await deleteGenerationMutation({ id: jobId });
|
|
1398
|
+
if (result2.error) {
|
|
1399
|
+
throw new Error(result2.error.message);
|
|
1400
|
+
}
|
|
1401
|
+
if (!result2.data?.deleteGeneration) {
|
|
1402
|
+
throw new Error("Failed to delete generation");
|
|
1403
|
+
}
|
|
1404
|
+
const controller = abortControllers.current.get(jobId);
|
|
1405
|
+
if (controller) {
|
|
1406
|
+
controller.abort();
|
|
1407
|
+
abortControllers.current.delete(jobId);
|
|
1408
|
+
}
|
|
1409
|
+
if (progress?.jobId === jobId) {
|
|
1410
|
+
setProgress(null);
|
|
1411
|
+
setResult(null);
|
|
1412
|
+
setIsGenerating(false);
|
|
1413
|
+
}
|
|
1414
|
+
setHistory((prev) => prev.filter((item) => item.jobId !== jobId));
|
|
1415
|
+
} catch (err) {
|
|
1416
|
+
setError(
|
|
1417
|
+
err instanceof Error ? err : new Error("Failed to delete generation")
|
|
1418
|
+
);
|
|
1419
|
+
throw err;
|
|
1420
|
+
}
|
|
1421
|
+
},
|
|
1422
|
+
[deleteGenerationMutation, progress]
|
|
1423
|
+
);
|
|
1387
1424
|
const clearHistory = (0, import_react6.useCallback)(() => {
|
|
1388
1425
|
setHistory([]);
|
|
1389
1426
|
}, []);
|
|
@@ -1395,6 +1432,7 @@ function useGeneration() {
|
|
|
1395
1432
|
submit,
|
|
1396
1433
|
cancel,
|
|
1397
1434
|
retry,
|
|
1435
|
+
deleteGeneration,
|
|
1398
1436
|
history,
|
|
1399
1437
|
clearHistory
|
|
1400
1438
|
};
|
|
@@ -1417,21 +1455,44 @@ function useGenerators(options = {}) {
|
|
|
1417
1455
|
};
|
|
1418
1456
|
}
|
|
1419
1457
|
|
|
1420
|
-
// src/hooks/
|
|
1458
|
+
// src/hooks/useMultiUpload.ts
|
|
1421
1459
|
var import_react8 = require("react");
|
|
1422
1460
|
var import_urql7 = require("urql");
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1461
|
+
var uploadIdCounter = 0;
|
|
1462
|
+
function generateUploadId() {
|
|
1463
|
+
return `upload-${Date.now()}-${++uploadIdCounter}`;
|
|
1464
|
+
}
|
|
1465
|
+
function getFileName(source) {
|
|
1466
|
+
if (typeof source === "string") {
|
|
1467
|
+
try {
|
|
1468
|
+
const url = new URL(source);
|
|
1469
|
+
const pathParts = url.pathname.split("/");
|
|
1470
|
+
return pathParts[pathParts.length - 1] || source;
|
|
1471
|
+
} catch {
|
|
1472
|
+
return source;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
return source.name;
|
|
1476
|
+
}
|
|
1477
|
+
function useMultiUpload() {
|
|
1478
|
+
const [uploads, setUploads] = (0, import_react8.useState)([]);
|
|
1479
|
+
const abortControllersRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
1427
1480
|
const { apiUrl } = useApiConfig();
|
|
1428
1481
|
const auth = useAuth();
|
|
1429
1482
|
const [, uploadFromUrlMutation] = (0, import_urql7.useMutation)(UPLOAD_ARTIFACT_FROM_URL);
|
|
1430
|
-
const
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1483
|
+
const updateUpload = (0, import_react8.useCallback)(
|
|
1484
|
+
(uploadId, updates) => {
|
|
1485
|
+
setUploads(
|
|
1486
|
+
(prev) => prev.map(
|
|
1487
|
+
(item) => item.id === uploadId ? { ...item, ...updates } : item
|
|
1488
|
+
)
|
|
1489
|
+
);
|
|
1490
|
+
},
|
|
1491
|
+
[]
|
|
1492
|
+
);
|
|
1493
|
+
const uploadSingle = (0, import_react8.useCallback)(
|
|
1494
|
+
async (uploadId, request) => {
|
|
1495
|
+
updateUpload(uploadId, { status: "uploading", progress: 0 });
|
|
1435
1496
|
try {
|
|
1436
1497
|
if (typeof request.source === "string") {
|
|
1437
1498
|
const result2 = await uploadFromUrlMutation({
|
|
@@ -1449,9 +1510,7 @@ function useUpload() {
|
|
|
1449
1510
|
if (!result2.data?.uploadArtifact) {
|
|
1450
1511
|
throw new Error("Upload failed");
|
|
1451
1512
|
}
|
|
1452
|
-
|
|
1453
|
-
setIsUploading(false);
|
|
1454
|
-
return {
|
|
1513
|
+
const uploadResult = {
|
|
1455
1514
|
id: result2.data.uploadArtifact.id,
|
|
1456
1515
|
storageUrl: result2.data.uploadArtifact.storageUrl,
|
|
1457
1516
|
thumbnailUrl: result2.data.uploadArtifact.thumbnailUrl,
|
|
@@ -1459,6 +1518,12 @@ function useUpload() {
|
|
|
1459
1518
|
artifactType: result2.data.uploadArtifact.artifactType,
|
|
1460
1519
|
generatorName: result2.data.uploadArtifact.generatorName
|
|
1461
1520
|
};
|
|
1521
|
+
updateUpload(uploadId, {
|
|
1522
|
+
status: "completed",
|
|
1523
|
+
progress: 100,
|
|
1524
|
+
result: uploadResult
|
|
1525
|
+
});
|
|
1526
|
+
return uploadResult;
|
|
1462
1527
|
}
|
|
1463
1528
|
const formData = new FormData();
|
|
1464
1529
|
formData.append("board_id", request.boardId);
|
|
@@ -1475,68 +1540,128 @@ function useUpload() {
|
|
|
1475
1540
|
if (token) {
|
|
1476
1541
|
headers.Authorization = `Bearer ${token}`;
|
|
1477
1542
|
}
|
|
1478
|
-
const result = await new Promise(
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
const data = JSON.parse(xhr.responseText);
|
|
1490
|
-
resolve({
|
|
1491
|
-
id: data.id,
|
|
1492
|
-
storageUrl: data.storageUrl,
|
|
1493
|
-
thumbnailUrl: data.thumbnailUrl,
|
|
1494
|
-
status: "completed",
|
|
1495
|
-
artifactType: data.artifactType,
|
|
1496
|
-
generatorName: data.generatorName
|
|
1497
|
-
});
|
|
1498
|
-
} catch (err) {
|
|
1499
|
-
reject(new Error("Failed to parse response"));
|
|
1543
|
+
const result = await new Promise(
|
|
1544
|
+
(resolve, reject) => {
|
|
1545
|
+
const xhr = new XMLHttpRequest();
|
|
1546
|
+
abortControllersRef.current.set(uploadId, () => xhr.abort());
|
|
1547
|
+
const cleanup = () => {
|
|
1548
|
+
abortControllersRef.current.delete(uploadId);
|
|
1549
|
+
};
|
|
1550
|
+
xhr.upload.addEventListener("progress", (e) => {
|
|
1551
|
+
if (e.lengthComputable) {
|
|
1552
|
+
const percentComplete = e.loaded / e.total * 100;
|
|
1553
|
+
updateUpload(uploadId, { progress: percentComplete });
|
|
1500
1554
|
}
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1555
|
+
});
|
|
1556
|
+
xhr.addEventListener("load", () => {
|
|
1557
|
+
cleanup();
|
|
1558
|
+
if (xhr.status === 200) {
|
|
1559
|
+
try {
|
|
1560
|
+
const data = JSON.parse(xhr.responseText);
|
|
1561
|
+
resolve({
|
|
1562
|
+
id: data.id,
|
|
1563
|
+
storageUrl: data.storageUrl,
|
|
1564
|
+
thumbnailUrl: data.thumbnailUrl,
|
|
1565
|
+
status: "completed",
|
|
1566
|
+
artifactType: data.artifactType,
|
|
1567
|
+
generatorName: data.generatorName
|
|
1568
|
+
});
|
|
1569
|
+
} catch (err) {
|
|
1570
|
+
reject(new Error("Failed to parse response"));
|
|
1571
|
+
}
|
|
1572
|
+
} else {
|
|
1573
|
+
try {
|
|
1574
|
+
const errorData = JSON.parse(xhr.responseText);
|
|
1575
|
+
reject(
|
|
1576
|
+
new Error(
|
|
1577
|
+
errorData.detail || `Upload failed: ${xhr.statusText}`
|
|
1578
|
+
)
|
|
1579
|
+
);
|
|
1580
|
+
} catch {
|
|
1581
|
+
reject(new Error(`Upload failed: ${xhr.statusText}`));
|
|
1582
|
+
}
|
|
1507
1583
|
}
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1584
|
+
});
|
|
1585
|
+
xhr.addEventListener("error", () => {
|
|
1586
|
+
cleanup();
|
|
1587
|
+
reject(new Error("Upload failed: Network error"));
|
|
1588
|
+
});
|
|
1589
|
+
xhr.addEventListener("abort", () => {
|
|
1590
|
+
cleanup();
|
|
1591
|
+
reject(new Error("Upload cancelled"));
|
|
1592
|
+
});
|
|
1593
|
+
xhr.addEventListener("loadend", () => {
|
|
1594
|
+
cleanup();
|
|
1595
|
+
});
|
|
1596
|
+
xhr.open("POST", `${apiUrl}/api/uploads/artifact`);
|
|
1597
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
1598
|
+
xhr.setRequestHeader(key, value);
|
|
1599
|
+
});
|
|
1600
|
+
xhr.send(formData);
|
|
1601
|
+
}
|
|
1602
|
+
);
|
|
1603
|
+
updateUpload(uploadId, {
|
|
1604
|
+
status: "completed",
|
|
1605
|
+
progress: 100,
|
|
1606
|
+
result
|
|
1521
1607
|
});
|
|
1522
|
-
setProgress(100);
|
|
1523
|
-
setIsUploading(false);
|
|
1524
1608
|
return result;
|
|
1525
1609
|
} catch (err) {
|
|
1526
1610
|
const uploadError = err instanceof Error ? err : new Error("Upload failed");
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1611
|
+
updateUpload(uploadId, {
|
|
1612
|
+
status: "failed",
|
|
1613
|
+
error: uploadError
|
|
1614
|
+
});
|
|
1530
1615
|
throw uploadError;
|
|
1531
1616
|
}
|
|
1532
1617
|
},
|
|
1533
|
-
[uploadFromUrlMutation, apiUrl, auth]
|
|
1618
|
+
[uploadFromUrlMutation, apiUrl, auth, updateUpload]
|
|
1534
1619
|
);
|
|
1620
|
+
const uploadMultiple = (0, import_react8.useCallback)(
|
|
1621
|
+
async (requests) => {
|
|
1622
|
+
const newUploads = requests.map((request) => ({
|
|
1623
|
+
id: generateUploadId(),
|
|
1624
|
+
file: request.source,
|
|
1625
|
+
fileName: getFileName(request.source),
|
|
1626
|
+
status: "pending",
|
|
1627
|
+
progress: 0
|
|
1628
|
+
}));
|
|
1629
|
+
setUploads((prev) => [...prev, ...newUploads]);
|
|
1630
|
+
const results = await Promise.allSettled(
|
|
1631
|
+
requests.map(
|
|
1632
|
+
(request, index) => uploadSingle(newUploads[index].id, request)
|
|
1633
|
+
)
|
|
1634
|
+
);
|
|
1635
|
+
const successfulResults = [];
|
|
1636
|
+
results.forEach((result) => {
|
|
1637
|
+
if (result.status === "fulfilled") {
|
|
1638
|
+
successfulResults.push(result.value);
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
return successfulResults;
|
|
1642
|
+
},
|
|
1643
|
+
[uploadSingle]
|
|
1644
|
+
);
|
|
1645
|
+
const clearUploads = (0, import_react8.useCallback)(() => {
|
|
1646
|
+
abortControllersRef.current.forEach((abort) => abort());
|
|
1647
|
+
abortControllersRef.current.clear();
|
|
1648
|
+
setUploads([]);
|
|
1649
|
+
}, []);
|
|
1650
|
+
const cancelUpload = (0, import_react8.useCallback)((uploadId) => {
|
|
1651
|
+
const abort = abortControllersRef.current.get(uploadId);
|
|
1652
|
+
if (abort) {
|
|
1653
|
+
abort();
|
|
1654
|
+
}
|
|
1655
|
+
}, []);
|
|
1656
|
+
const isUploading = uploads.some((u) => u.status === "uploading");
|
|
1657
|
+
const overallProgress = uploads.length > 0 ? uploads.reduce((sum, u) => sum + u.progress, 0) / uploads.length : 0;
|
|
1535
1658
|
return {
|
|
1536
|
-
|
|
1659
|
+
uploadMultiple,
|
|
1660
|
+
uploads,
|
|
1537
1661
|
isUploading,
|
|
1538
|
-
|
|
1539
|
-
|
|
1662
|
+
overallProgress,
|
|
1663
|
+
clearUploads,
|
|
1664
|
+
cancelUpload
|
|
1540
1665
|
};
|
|
1541
1666
|
}
|
|
1542
1667
|
|
|
@@ -1654,6 +1779,7 @@ var VERSION = "0.1.0";
|
|
|
1654
1779
|
CREATE_BOARD,
|
|
1655
1780
|
CREATE_GENERATION,
|
|
1656
1781
|
DELETE_BOARD,
|
|
1782
|
+
DELETE_GENERATION,
|
|
1657
1783
|
DESCENDANT_NODE_FRAGMENT,
|
|
1658
1784
|
GENERATION_FRAGMENT,
|
|
1659
1785
|
GET_ANCESTRY,
|
|
@@ -1693,6 +1819,6 @@ var VERSION = "0.1.0";
|
|
|
1693
1819
|
useGenerators,
|
|
1694
1820
|
useInputArtifacts,
|
|
1695
1821
|
useLineage,
|
|
1696
|
-
|
|
1822
|
+
useMultiUpload
|
|
1697
1823
|
});
|
|
1698
1824
|
//# sourceMappingURL=index.js.map
|