@sparkstudio/storage-ui 1.0.12 → 1.0.13

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.cjs CHANGED
@@ -24,11 +24,18 @@ __export(index_exports, {
24
24
  Container: () => Container,
25
25
  ContainerDTO: () => ContainerDTO,
26
26
  ContainerType: () => ContainerType,
27
+ ContainerUploadPanel: () => ContainerUploadPanel,
27
28
  Home: () => Home,
28
29
  HomeView: () => HomeView,
29
30
  S3: () => S3,
30
31
  SparkStudioStorageSDK: () => SparkStudioStorageSDK,
31
- UploadContainer: () => UploadContainer
32
+ UploadContainer: () => UploadContainer,
33
+ UploadDropzone: () => UploadDropzone,
34
+ UploadFilePicker: () => UploadFilePicker,
35
+ UploadFileToS3: () => UploadFileToS3,
36
+ UploadProgressList: () => UploadProgressList,
37
+ UseContainers: () => UseContainers,
38
+ UseUploadManager: () => UseUploadManager
32
39
  });
33
40
  module.exports = __toCommonJS(index_exports);
34
41
 
@@ -240,75 +247,246 @@ var ContainerType = /* @__PURE__ */ ((ContainerType2) => {
240
247
  return ContainerType2;
241
248
  })(ContainerType || {});
242
249
 
250
+ // src/components/ContainerUploadPanel.tsx
251
+ var import_react7 = require("react");
252
+
243
253
  // src/components/UploadContainer.tsx
254
+ var import_react5 = require("react");
255
+
256
+ // src/components/UploadDropzone.tsx
244
257
  var import_react = require("react");
245
258
  var import_jsx_runtime = require("react/jsx-runtime");
246
- var UploadContainer = ({
247
- title = "Upload files",
248
- description = "Drag and drop files here, or click the button to browse.",
249
- multiple = true,
259
+ var UploadDropzone = ({
260
+ isDragging,
261
+ onDragOver,
262
+ onDragLeave,
263
+ onDrop
264
+ }) => {
265
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
266
+ "div",
267
+ {
268
+ className: "border rounded-3 p-4 text-center mb-3 d-flex flex-column align-items-center justify-content-center " + (isDragging ? "bg-light border-primary" : "border-secondary border-dashed"),
269
+ style: { cursor: "pointer", minHeight: "140px" },
270
+ onDragOver,
271
+ onDragLeave,
272
+ onDrop,
273
+ children: [
274
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { className: "bi bi-cloud-arrow-up fs-1 mb-2" }),
275
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mb-2", children: "Drop files here" }),
276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "text-muted", children: "or click the button below" })
277
+ ]
278
+ }
279
+ );
280
+ };
281
+
282
+ // src/components/UploadFilePicker.tsx
283
+ var import_react2 = require("react");
284
+ var import_jsx_runtime2 = require("react/jsx-runtime");
285
+ var UploadFilePicker = ({
286
+ multiple,
250
287
  accept,
251
- onFilesSelected,
252
- autoUpload = false,
253
- getPresignedUrl,
254
- onUploadComplete,
255
- onUploadError
288
+ fileNames,
289
+ onFileChange
256
290
  }) => {
257
- const [isDragging, setIsDragging] = (0, import_react.useState)(false);
258
- const [fileNames, setFileNames] = (0, import_react.useState)([]);
259
- const [uploads, setUploads] = (0, import_react.useState)([]);
260
- const startUploadsIfNeeded = (files) => {
261
- if (!autoUpload || !getPresignedUrl) return;
262
- const newUploads = Array.from(files).map((file) => ({
263
- id: `${file.name}-${file.size}-${file.lastModified}-${Math.random()}`,
264
- file,
265
- progress: 0,
266
- status: "pending"
267
- }));
268
- setUploads((prev) => [...prev, ...newUploads]);
269
- newUploads.forEach((upload) => {
270
- uploadFile(upload);
271
- });
272
- };
273
- const uploadFile = async (upload) => {
274
- setUploads(
275
- (prev) => prev.map(
276
- (u) => u.id === upload.id ? { ...u, status: "uploading", progress: 0 } : u
291
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "d-flex gap-2 align-items-center", children: [
292
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "btn btn-primary mb-0", children: [
293
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "bi bi-folder2-open me-2" }),
294
+ "Browse files",
295
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
296
+ "input",
297
+ {
298
+ type: "file",
299
+ className: "d-none",
300
+ multiple,
301
+ accept,
302
+ onChange: onFileChange
303
+ }
277
304
  )
278
- );
279
- try {
280
- if (!getPresignedUrl) {
281
- throw new Error("getPresignedUrl is not provided.");
305
+ ] }),
306
+ fileNames.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-grow-1", children: [
307
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "small text-muted", children: "Selected:" }),
308
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { className: "mb-0 small", children: fileNames.map((name) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: name }, name)) })
309
+ ] })
310
+ ] });
311
+ };
312
+
313
+ // src/components/UploadProgressList.tsx
314
+ var import_react3 = require("react");
315
+ var import_jsx_runtime3 = require("react/jsx-runtime");
316
+ var UploadProgressList = ({
317
+ uploads
318
+ }) => {
319
+ if (uploads.length === 0) return null;
320
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mt-3", children: uploads.map((u) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mb-2", children: [
321
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "d-flex justify-content-between small mb-1", children: [
322
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
323
+ u.file.name,
324
+ " - ",
325
+ u?.publicUrl ?? ""
326
+ ] }),
327
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: u.status === "success" ? "Completed" : u.status === "error" ? "Error" : `${u.progress}%` })
328
+ ] }),
329
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "progress", style: { height: "6px" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
330
+ "div",
331
+ {
332
+ className: "progress-bar " + (u.status === "success" ? "bg-success" : u.status === "error" ? "bg-danger" : ""),
333
+ role: "progressbar",
334
+ style: { width: `${u.progress}%` },
335
+ "aria-valuenow": u.progress,
336
+ "aria-valuemin": 0,
337
+ "aria-valuemax": 100
282
338
  }
283
- const presignedUrl = await getPresignedUrl(upload.file);
284
- const url = presignedUrl?.PresignedUrl ?? "";
285
- await uploadFileToS3(upload.file, url, (progress) => {
286
- setUploads(
287
- (prev) => prev.map(
288
- (u) => u.id === upload.id ? { ...u, progress } : u
339
+ ) }),
340
+ u.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "text-danger small mt-1", children: u.error ?? "Upload failed" })
341
+ ] }, u.id)) });
342
+ };
343
+
344
+ // src/hooks/UseUploadManager.ts
345
+ var import_react4 = require("react");
346
+
347
+ // src/engines/UploadFileToS3.ts
348
+ async function UploadFileToS3(file, presignedUrl, onProgress) {
349
+ return new Promise((resolve, reject) => {
350
+ const xhr = new XMLHttpRequest();
351
+ xhr.open("PUT", presignedUrl);
352
+ xhr.upload.onprogress = (event) => {
353
+ if (!event.lengthComputable) return;
354
+ const percent = Math.round(event.loaded / event.total * 100);
355
+ onProgress(percent);
356
+ };
357
+ xhr.onload = () => {
358
+ if (xhr.status >= 200 && xhr.status < 300) {
359
+ onProgress(100);
360
+ resolve();
361
+ } else {
362
+ reject(
363
+ new Error(
364
+ `S3 upload failed with status ${xhr.status}: ${xhr.statusText}`
289
365
  )
290
366
  );
291
- });
292
- const fileUrl = url.split("?")[0];
293
- setUploads(
294
- (prev) => prev.map(
295
- (u) => u.id === upload.id ? { ...u, status: "success", progress: 100, s3Url: fileUrl, publicUrl: presignedUrl.PublicUrl } : u
296
- )
297
- );
298
- onUploadComplete?.(upload.file, fileUrl);
299
- } catch (err) {
300
- let message = "Upload failed";
301
- if (err instanceof Error) {
302
- message = err.message;
303
367
  }
368
+ };
369
+ xhr.onerror = () => {
370
+ reject(new Error("Network error while uploading to S3"));
371
+ };
372
+ xhr.setRequestHeader(
373
+ "Content-Type",
374
+ file.type || "application/octet-stream"
375
+ );
376
+ xhr.send(file);
377
+ });
378
+ }
379
+
380
+ // src/hooks/UseUploadManager.ts
381
+ function UseUploadManager({
382
+ autoUpload = false,
383
+ getPresignedUrl,
384
+ onUploadComplete,
385
+ onUploadError
386
+ }) {
387
+ const [uploads, setUploads] = (0, import_react4.useState)([]);
388
+ const createUploadStates = (files) => Array.from(files).map((file) => ({
389
+ id: `${file.name}-${file.size}-${file.lastModified}-${Math.random()}`,
390
+ file,
391
+ progress: 0,
392
+ status: "pending"
393
+ }));
394
+ const uploadFile = (0, import_react4.useCallback)(
395
+ async (upload) => {
304
396
  setUploads(
305
397
  (prev) => prev.map(
306
- (u) => u.id === upload.id ? { ...u, status: "error", error: message } : u
398
+ (u) => u.id === upload.id ? { ...u, status: "uploading", progress: 0 } : u
307
399
  )
308
400
  );
309
- onUploadError?.(upload.file, err instanceof Error ? err : new Error(message));
310
- }
401
+ try {
402
+ if (!getPresignedUrl) {
403
+ throw new Error("getPresignedUrl is not provided.");
404
+ }
405
+ const presignedUrl = await getPresignedUrl(
406
+ upload.file
407
+ );
408
+ const url = presignedUrl?.PresignedUrl ?? "";
409
+ await UploadFileToS3(upload.file, url, (progress) => {
410
+ setUploads(
411
+ (prev) => prev.map(
412
+ (u) => u.id === upload.id ? { ...u, progress } : u
413
+ )
414
+ );
415
+ });
416
+ const fileUrl = url.split("?")[0];
417
+ setUploads(
418
+ (prev) => prev.map(
419
+ (u) => u.id === upload.id ? {
420
+ ...u,
421
+ status: "success",
422
+ progress: 100,
423
+ s3Url: fileUrl,
424
+ // assumes your DTO has PublicUrl
425
+ publicUrl: presignedUrl.PublicUrl
426
+ } : u
427
+ )
428
+ );
429
+ onUploadComplete?.(upload.file, fileUrl);
430
+ } catch (err) {
431
+ let message = "Upload failed";
432
+ if (err instanceof Error) {
433
+ message = err.message;
434
+ }
435
+ setUploads(
436
+ (prev) => prev.map(
437
+ (u) => u.id === upload.id ? { ...u, status: "error", error: message } : u
438
+ )
439
+ );
440
+ onUploadError?.(
441
+ upload.file,
442
+ err instanceof Error ? err : new Error(message)
443
+ );
444
+ }
445
+ },
446
+ [getPresignedUrl, onUploadComplete, onUploadError]
447
+ );
448
+ const startUploadsIfNeeded = (0, import_react4.useCallback)(
449
+ (files) => {
450
+ if (!autoUpload || !getPresignedUrl) return;
451
+ const newUploads = createUploadStates(files);
452
+ setUploads((prev) => [...prev, ...newUploads]);
453
+ newUploads.forEach((upload) => {
454
+ void uploadFile(upload);
455
+ });
456
+ },
457
+ [autoUpload, getPresignedUrl, uploadFile]
458
+ );
459
+ const resetUploads = (0, import_react4.useCallback)(() => setUploads([]), []);
460
+ return {
461
+ uploads,
462
+ startUploadsIfNeeded,
463
+ resetUploads
311
464
  };
465
+ }
466
+
467
+ // src/components/UploadContainer.tsx
468
+ var import_jsx_runtime4 = require("react/jsx-runtime");
469
+ var UploadContainer = ({
470
+ title = "Upload files",
471
+ description = "Drag and drop files here, or click the button to browse.",
472
+ multiple = true,
473
+ accept,
474
+ onFilesSelected,
475
+ existingFiles = [],
476
+ onExistingFileClick,
477
+ autoUpload = false,
478
+ getPresignedUrl,
479
+ onUploadComplete,
480
+ onUploadError
481
+ }) => {
482
+ const [isDragging, setIsDragging] = (0, import_react5.useState)(false);
483
+ const [fileNames, setFileNames] = (0, import_react5.useState)([]);
484
+ const { uploads, startUploadsIfNeeded } = UseUploadManager({
485
+ autoUpload,
486
+ getPresignedUrl,
487
+ onUploadComplete,
488
+ onUploadError
489
+ });
312
490
  const handleDragOver = (e) => {
313
491
  e.preventDefault();
314
492
  setIsDragging(true);
@@ -333,151 +511,205 @@ var UploadContainer = ({
333
511
  onFilesSelected?.(files);
334
512
  startUploadsIfNeeded(files);
335
513
  };
336
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "container my-3", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "card shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "card-body", children: [
337
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h5", { className: "card-title mb-2", children: title }),
338
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "card-text text-muted", children: description }),
339
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
340
- "div",
514
+ const handleExistingFileClickInternal = (file) => {
515
+ if (onExistingFileClick) {
516
+ onExistingFileClick(file);
517
+ return;
518
+ }
519
+ const a = document.createElement("a");
520
+ a.download = file.Name ?? "";
521
+ a.target = "_blank";
522
+ a.rel = "noopener noreferrer";
523
+ document.body.appendChild(a);
524
+ a.click();
525
+ document.body.removeChild(a);
526
+ };
527
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
528
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h5", { className: "card-title mb-2", children: title }),
529
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "card-text text-muted", children: description }),
530
+ existingFiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mb-3", children: [
531
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h6", { className: "mb-2", children: "Existing files" }),
532
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "list-group", children: existingFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
533
+ "li",
534
+ {
535
+ className: "list-group-item d-flex justify-content-between align-items-center",
536
+ style: { cursor: "pointer" },
537
+ onClick: () => handleExistingFileClickInternal(file),
538
+ children: [
539
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: file.Name }),
540
+ typeof file.FileSize === "number" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { className: "text-muted", children: [
541
+ (file.FileSize / 1024).toFixed(1),
542
+ " KB"
543
+ ] })
544
+ ]
545
+ },
546
+ file.Id
547
+ )) })
548
+ ] }),
549
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
550
+ UploadDropzone,
341
551
  {
342
- className: "border rounded-3 p-4 text-center mb-3 d-flex flex-column align-items-center justify-content-center " + (isDragging ? "bg-light border-primary" : "border-secondary border-dashed"),
343
- style: { cursor: "pointer", minHeight: "140px" },
552
+ isDragging,
344
553
  onDragOver: handleDragOver,
345
554
  onDragLeave: handleDragLeave,
346
- onDrop: handleDrop,
347
- children: [
348
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { className: "bi bi-cloud-arrow-up fs-1 mb-2" }),
349
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mb-2", children: "Drop files here" }),
350
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "text-muted", children: "or click the button below" })
351
- ]
555
+ onDrop: handleDrop
352
556
  }
353
557
  ),
354
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "d-flex gap-2 align-items-center", children: [
355
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "btn btn-primary mb-0", children: [
356
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { className: "bi bi-folder2-open me-2" }),
357
- "Browse files",
358
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
359
- "input",
360
- {
361
- type: "file",
362
- className: "d-none",
363
- multiple,
364
- accept,
365
- onChange: handleFileChange
366
- }
367
- )
368
- ] }),
369
- fileNames.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-grow-1", children: [
370
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "small text-muted", children: "Selected:" }),
371
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "mb-0 small", children: fileNames.map((name) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: name }, name)) })
372
- ] })
373
- ] }),
374
- uploads.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-3", children: uploads.map((u) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-2", children: [
375
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "d-flex justify-content-between small mb-1", children: [
376
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
377
- u.file.name,
378
- " - ",
379
- u?.publicUrl ?? ""
380
- ] }),
381
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: u.status === "success" ? "Completed" : u.status === "error" ? "Error" : `${u.progress}%` })
382
- ] }),
383
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "progress", style: { height: "6px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
384
- "div",
385
- {
386
- className: "progress-bar " + (u.status === "success" ? "bg-success" : u.status === "error" ? "bg-danger" : ""),
387
- role: "progressbar",
388
- style: { width: `${u.progress}%` },
389
- "aria-valuenow": u.progress,
390
- "aria-valuemin": 0,
391
- "aria-valuemax": 100
392
- }
393
- ) }),
394
- u.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-danger small mt-1", children: u.error ?? "Upload failed" })
395
- ] }, u.id)) })
396
- ] }) }) });
397
- };
398
- async function uploadFileToS3(file, presignedUrl, onProgress) {
399
- return new Promise((resolve, reject) => {
400
- const xhr = new XMLHttpRequest();
401
- xhr.open("PUT", presignedUrl);
402
- xhr.upload.onprogress = (event) => {
403
- if (!event.lengthComputable) return;
404
- const percent = Math.round(event.loaded / event.total * 100);
405
- onProgress(percent);
406
- };
407
- xhr.onload = () => {
408
- if (xhr.status >= 200 && xhr.status < 300) {
409
- onProgress(100);
410
- resolve();
411
- } else {
412
- reject(
413
- new Error(`S3 upload failed with status ${xhr.status}: ${xhr.statusText}`)
414
- );
558
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
559
+ UploadFilePicker,
560
+ {
561
+ multiple,
562
+ accept,
563
+ fileNames,
564
+ onFileChange: handleFileChange
415
565
  }
416
- };
417
- xhr.onerror = () => {
418
- reject(new Error("Network error while uploading to S3"));
419
- };
420
- xhr.setRequestHeader(
421
- "Content-Type",
422
- file.type || "application/octet-stream"
423
- );
424
- xhr.send(file);
425
- });
566
+ ),
567
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UploadProgressList, { uploads })
568
+ ] });
569
+ };
570
+
571
+ // src/hooks/UseContainers.ts
572
+ var import_react6 = require("react");
573
+ function UseContainers({ apiBaseUrl, parentId }) {
574
+ const [containers, setContainers] = (0, import_react6.useState)([]);
575
+ const [loading, setLoading] = (0, import_react6.useState)(false);
576
+ const [error, setError] = (0, import_react6.useState)(null);
577
+ const load = async () => {
578
+ setLoading(true);
579
+ setError(null);
580
+ try {
581
+ const sdkDb = new SparkStudioStorageSDK(
582
+ "https://lf9zyufpuk.execute-api.us-east-2.amazonaws.com/Prod"
583
+ );
584
+ const result = await sdkDb.container.ReadRootContainers();
585
+ setContainers(result);
586
+ } catch (err) {
587
+ setError(err);
588
+ } finally {
589
+ setLoading(false);
590
+ }
591
+ };
592
+ (0, import_react6.useEffect)(() => {
593
+ void load();
594
+ }, [apiBaseUrl, parentId]);
595
+ return {
596
+ containers,
597
+ loading,
598
+ error,
599
+ reload: load
600
+ };
426
601
  }
427
602
 
428
- // src/views/HomeView.tsx
429
- var import_authentication_ui = require("@sparkstudio/authentication-ui");
430
- var import_jsx_runtime2 = require("react/jsx-runtime");
431
- function HomeView() {
432
- function handleOnLoginSuccess(user) {
433
- alert(user?.Id);
434
- }
603
+ // src/components/ContainerUploadPanel.tsx
604
+ var import_jsx_runtime5 = require("react/jsx-runtime");
605
+ var ContainerUploadPanel = ({
606
+ containerApiBaseUrl,
607
+ parentContainerId,
608
+ title = "Upload files",
609
+ description = "Drop files to upload. Existing files are listed below."
610
+ }) => {
611
+ const { containers, loading, error, reload } = UseContainers({
612
+ apiBaseUrl: containerApiBaseUrl,
613
+ parentId: parentContainerId
614
+ });
435
615
  const getPresignedUrl = async (file) => {
436
- const sdkDb = new SparkStudioStorageSDK("https://lf9zyufpuk.execute-api.us-east-2.amazonaws.com/Prod");
437
- const sdkS3 = new SparkStudioStorageSDK("https://iq0gmcn0pd.execute-api.us-east-2.amazonaws.com/Prod");
438
- const containerDTO = await sdkDb.container.CreateFileContainer(file.name, file.size, encodeURIComponent(file.type));
616
+ const sdkDb = new SparkStudioStorageSDK(
617
+ "https://lf9zyufpuk.execute-api.us-east-2.amazonaws.com/Prod"
618
+ );
619
+ const sdkS3 = new SparkStudioStorageSDK(
620
+ "https://iq0gmcn0pd.execute-api.us-east-2.amazonaws.com/Prod"
621
+ );
622
+ const containerDTO = await sdkDb.container.CreateFileContainer(
623
+ file.name,
624
+ file.size,
625
+ encodeURIComponent(file.type)
626
+ );
439
627
  const resultS3 = await sdkS3.s3.GetPreSignedUrl(containerDTO);
440
628
  return resultS3;
441
629
  };
442
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
630
+ const handleUploadComplete = async (file, s3Url) => {
631
+ console.log("Upload complete:", file.name, s3Url);
632
+ await reload();
633
+ };
634
+ const handleUploadError = (file, err) => {
635
+ console.error("Upload failed:", file.name, err);
636
+ };
637
+ const handleExistingFileClick = (file) => {
638
+ const downloadUrl = `${containerApiBaseUrl}/api/Container/Download/${file.Id}`;
639
+ const a = document.createElement("a");
640
+ a.href = downloadUrl;
641
+ a.download = file.Name ?? "";
642
+ a.target = "_blank";
643
+ a.rel = "noopener noreferrer";
644
+ document.body.appendChild(a);
645
+ a.click();
646
+ document.body.removeChild(a);
647
+ };
648
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
649
+ loading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "Loading existing files\u2026" }),
650
+ error && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "text-danger", children: [
651
+ "Failed to load containers: ",
652
+ error.message
653
+ ] }),
654
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
655
+ UploadContainer,
656
+ {
657
+ title,
658
+ description,
659
+ existingFiles: containers,
660
+ onExistingFileClick: handleExistingFileClick,
661
+ autoUpload: true,
662
+ getPresignedUrl,
663
+ onUploadComplete: handleUploadComplete,
664
+ onUploadError: handleUploadError
665
+ }
666
+ )
667
+ ] });
668
+ };
669
+
670
+ // src/views/HomeView.tsx
671
+ var import_authentication_ui = require("@sparkstudio/authentication-ui");
672
+ var import_jsx_runtime6 = require("react/jsx-runtime");
673
+ function HomeView() {
674
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
443
675
  import_authentication_ui.AuthenticatorProvider,
444
676
  {
445
677
  googleClientId: import_authentication_ui.AppSettings.GoogleClientId,
446
678
  authenticationUrl: import_authentication_ui.AppSettings.AuthenticationUrl,
447
679
  accountsUrl: import_authentication_ui.AppSettings.AccountsUrl,
448
- onLoginSuccess: handleOnLoginSuccess,
449
- children: [
450
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_authentication_ui.UserInfoCard, {}),
451
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
452
- UploadContainer,
453
- {
454
- title: "Upload your files to S3",
455
- description: "Drag & drop or browse files. Each file will upload with its own progress bar.",
456
- multiple: true,
457
- accept: "*/*",
458
- autoUpload: true,
459
- getPresignedUrl,
460
- onUploadComplete: (file, s3Url) => {
461
- console.log("Uploaded", file.name, "to", s3Url);
462
- },
463
- onUploadError: (file, error) => {
464
- console.error("Failed to upload", file.name, error);
465
- }
466
- }
467
- )
468
- ]
680
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HomeContent, {})
469
681
  }
470
682
  );
471
683
  }
684
+ function HomeContent() {
685
+ const { user } = (0, import_authentication_ui.useUser)();
686
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
687
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_authentication_ui.UserInfoCard, {}),
688
+ user && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
689
+ ContainerUploadPanel,
690
+ {
691
+ containerApiBaseUrl: "https://lf9zyufpuk.execute-api.us-east-2.amazonaws.com/Prod",
692
+ storageApiBaseUrl: "https://iq0gmcn0pd.execute-api.us-east-2.amazonaws.com/Prod"
693
+ }
694
+ )
695
+ ] });
696
+ }
472
697
  // Annotate the CommonJS export names for ESM import in node:
473
698
  0 && (module.exports = {
474
699
  AWSPresignedUrlDTO,
475
700
  Container,
476
701
  ContainerDTO,
477
702
  ContainerType,
703
+ ContainerUploadPanel,
478
704
  Home,
479
705
  HomeView,
480
706
  S3,
481
707
  SparkStudioStorageSDK,
482
- UploadContainer
708
+ UploadContainer,
709
+ UploadDropzone,
710
+ UploadFilePicker,
711
+ UploadFileToS3,
712
+ UploadProgressList,
713
+ UseContainers,
714
+ UseUploadManager
483
715
  });