{
role="button"
onClick={() => onObjectClick(object)}
>
-
+
- {filename}
- {ext && {ext}}
+
+ {filename}
+
+ {ext && (
+ {ext}
+ )}
|
diff --git a/src/pages/buckets/manage/browse/types.ts b/src/pages/buckets/manage/browse/types.ts
index 272ce8c..3a84375 100644
--- a/src/pages/buckets/manage/browse/types.ts
+++ b/src/pages/buckets/manage/browse/types.ts
@@ -18,7 +18,27 @@ export type Object = {
url: string;
};
+export type UploadRowPhase = "uploading" | "finishing" | "paused";
+
+export type UploadRowStatus =
+ | "uploading"
+ | "paused"
+ | "finishing"
+ | "error";
+
+export type UploadRowItem = {
+ id: string;
+ bucket: string;
+ prefix: string;
+ key: string;
+ fileName: string;
+ size: number;
+ percent: number;
+ phase: UploadRowPhase;
+ status: UploadRowStatus;
+ errorMessage?: string;
+};
+
export type PutObjectPayload = {
key: string;
- file: File | null;
};
diff --git a/src/pages/buckets/manage/browse/upload-queue.tsx b/src/pages/buckets/manage/browse/upload-queue.tsx
new file mode 100644
index 0000000..39e187d
--- /dev/null
+++ b/src/pages/buckets/manage/browse/upload-queue.tsx
@@ -0,0 +1,234 @@
+import {
+ createContext,
+ useCallback,
+ useContext,
+ useMemo,
+ useRef,
+ useState,
+ type ReactNode,
+} from "react";
+import { useQueryClient } from "@tanstack/react-query";
+import { API_URL } from "@/lib/api";
+import { startPausableUpload } from "@/lib/pausable-upload";
+import { url } from "@/lib/utils";
+import { toUploadErrorMessage } from "./upload-status";
+import {
+ UploadRowItem,
+ UploadRowPhase,
+ UploadRowStatus,
+} from "./types";
+
+type ActiveUpload = {
+ pause: () => void;
+ resume: () => void;
+ abort: () => void;
+};
+
+type UploadQueueContextValue = {
+ items: UploadRowItem[];
+ enqueueFiles: (bucket: string, prefix: string, files: File[]) => void;
+ pauseUpload: (id: string) => void;
+ resumeUpload: (id: string) => void;
+ cancelUpload: (id: string) => void;
+ getItemsForLocation: (bucket: string, prefix: string) => UploadRowItem[];
+};
+
+const UploadQueueContext = createContext(null);
+
+const createUploadId = () =>
+ typeof crypto !== "undefined" && crypto.randomUUID
+ ? crypto.randomUUID()
+ : `upload-${Date.now()}-${Math.random().toString(36).slice(2)}`;
+
+const progressToStatus = (phase: UploadRowPhase): UploadRowStatus =>
+ phase === "finishing" ? "finishing" : "uploading";
+
+const createUploadItem = (
+ id: string,
+ bucket: string,
+ prefix: string,
+ file: File
+): UploadRowItem => ({
+ id,
+ bucket,
+ prefix,
+ key: prefix + file.name,
+ fileName: file.name,
+ size: file.size,
+ percent: 0,
+ phase: "uploading",
+ status: "uploading",
+});
+
+export const UploadQueueProvider = ({ children }: { children: ReactNode }) => {
+ const queryClient = useQueryClient();
+ const [items, setItems] = useState([]);
+ const activeRef = useRef |