From 3c767f8e052a702eb67ccef40b35ed5a9dda07a9 Mon Sep 17 00:00:00 2001 From: Juan Di Toro Date: Thu, 28 Mar 2024 23:59:11 +0100 Subject: [PATCH] fix: pinning progress bar is now fully working --- app/components/general-layout.tsx | 171 ++++++++++++++++++---------- app/data/pinning.ts | 2 +- app/hooks/usePinning.ts | 1 + app/providers/PinningProvider.tsx | 2 +- app/routes/file-manager/columns.tsx | 4 + app/routes/file-manager/index.tsx | 11 +- 6 files changed, 121 insertions(+), 70 deletions(-) diff --git a/app/components/general-layout.tsx b/app/components/general-layout.tsx index 9b23aac..f740ef1 100644 --- a/app/components/general-layout.tsx +++ b/app/components/general-layout.tsx @@ -2,7 +2,7 @@ import { Button } from "~/components/ui/button"; import logoPng from "~/images/lume-logo.png?url"; import lumeColorLogoPng from "~/images/lume-color-logo.png?url"; import discordLogoPng from "~/images/discord-logo.png?url"; -import { Link, useLocation } from "@remix-run/react"; +import { Form, Link, useLocation } from "@remix-run/react"; import { Dialog, DialogContent, @@ -46,6 +46,10 @@ import { TooltipProvider, } from "./ui/tooltip"; import filesize from "./lib/filesize"; +import { z } from "zod"; +import { getFormProps, useForm, useInputControl } from "@conform-to/react"; +import { getZodConstraint, parseWithZod } from "@conform-to/zod"; +import { ErrorList } from "./forms"; export const GeneralLayout = ({ children }: React.PropsWithChildren) => { const location = useLocation(); @@ -171,96 +175,139 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren) => { ); }; +const UploadFormSchema = z.object({ + uppyFiles: z.array(z.any()).min(1, { + message: "At least one file must be uploaded", + }), +}); + const UploadFileForm = () => { const { getRootProps, getInputProps, getFiles, - upload, state, removeFile, cancelAll, failedFiles, + upload, } = useUppy(); + const [form, fields] = useForm({ + constraint: getZodConstraint(UploadFormSchema), + shouldValidate: "onInput", + onValidate: ({ formData }) => { + const result = parseWithZod(formData, { + schema: UploadFormSchema, + }); + return result; + }, + onSubmit: (e) => { + e.preventDefault(); + return upload(); + }, + }); + + const inputProps = getInputProps(); + const files = useInputControl({ + key: fields.uppyFiles.key, + name: fields.uppyFiles.name, + formId: form.id + }); + const isUploading = state === "uploading"; const isCompleted = state === "completed"; const hasErrored = state === "error"; const hasStarted = state !== "idle" && state !== "initializing"; + const isValid = form.valid || getFiles().length > 0; const getFailedState = (id: string) => failedFiles.find((file) => file.id === id); + console.log({ files: getFiles() }); + return ( <> Upload Files - {!hasStarted ? ( -
- - -

Drag & Drop Files or Browse

+
+ {!hasStarted ? ( +
+ { + //@ts-expect-error -- conform has shitty typeinference for controls + files.change(getFiles()); + }} + /> + +

Drag & Drop Files or Browse

+
+ ) : null} + +
+ {getFiles().map((file) => ( + { + removeFile(id); + }} + failedState={getFailedState(file.id)} + /> + ))}
- ) : null} -
- {getFiles().map((file) => ( - { - removeFile(id); - }} - failedState={getFailedState(file.id)} - /> - ))} -
+ - {hasErrored ? ( -
-

An error occurred

-
- ) : null} + {hasStarted && !hasErrored ? ( +
+ + {isCompleted + ? "Upload completed" + : `${getFiles().length} files being uploaded`} +
+ ) : null} - {hasStarted && !hasErrored ? ( -
- - {isCompleted - ? "Upload completed" - : `${getFiles().length} files being uploaded`} -
- ) : null} + {isUploading ? ( + + + + ) : null} - {isUploading ? ( - - + + ) : null} + + {!hasStarted && !isCompleted && !isUploading ? ( + - - ) : null} - - {isCompleted ? ( - - - - ) : null} - - {!hasStarted && !isCompleted && !isUploading ? ( - - ) : null} + ) : null} + ); }; diff --git a/app/data/pinning.ts b/app/data/pinning.ts index fd292b6..8933256 100644 --- a/app/data/pinning.ts +++ b/app/data/pinning.ts @@ -60,7 +60,7 @@ export class PinningProcess { let allStatuses = Array.from(PinningProcess.instances.values()); let inProgress = allStatuses.some((status) => { PinningProcess.checkStatus(status.id); - return status.status !== "completed"; + return status.status !== "processing"; }); while (inProgress) { diff --git a/app/hooks/usePinning.ts b/app/hooks/usePinning.ts index 85cf387..47ee075 100644 --- a/app/hooks/usePinning.ts +++ b/app/hooks/usePinning.ts @@ -63,6 +63,7 @@ export const usePinning = () => { return { progressStatus: context.query.status, progressData: context.query.data, + fetchProgress: context.query.refetch, pinStatus, pinData, unpinStatus, diff --git a/app/providers/PinningProvider.tsx b/app/providers/PinningProvider.tsx index 8c9b363..f99c1a1 100644 --- a/app/providers/PinningProvider.tsx +++ b/app/providers/PinningProvider.tsx @@ -33,7 +33,7 @@ export const PinningProvider = ({ children }: React.PropsWithChildren) => { const queryResult = useQuery({ queryKey: ["pin-progress"], refetchInterval: (query) => { - if (!query.state.data || !query.state.data.items.length) { + if (!query.state.data?.items || query.state.data.items.length === 0) { return false; } diff --git a/app/routes/file-manager/columns.tsx b/app/routes/file-manager/columns.tsx index 615fd25..1bcd1f0 100644 --- a/app/routes/file-manager/columns.tsx +++ b/app/routes/file-manager/columns.tsx @@ -53,6 +53,10 @@ export const columns: ColumnDef[] = [ // enableSorting: false, // enableHiding: false, // }, + { + accessorKey: "name", + header: () => null, + }, { accessorKey: "cid", header: "CID", diff --git a/app/routes/file-manager/index.tsx b/app/routes/file-manager/index.tsx index e48dff7..45355c3 100644 --- a/app/routes/file-manager/index.tsx +++ b/app/routes/file-manager/index.tsx @@ -113,7 +113,7 @@ const PinFilesSchema = z.object({ }); const PinFilesForm = ({ close }: { close: () => void }) => { - const { bulkPin, pinStatus, pinData } = usePinning(); + const { bulkPin, pinStatus, fetchProgress } = usePinning(); const [form, fields] = useForm({ id: "pin-files", constraint: getZodConstraint(PinFilesSchema), @@ -131,13 +131,12 @@ const PinFilesForm = ({ close }: { close: () => void }) => { }, }); - console.log({pinStatus, pinData}) - useEffect(() => { if (pinStatus === "success") { + fetchProgress(); close(); } - }, [pinStatus, close]); + }, [pinStatus, fetchProgress, close]); return ( <> @@ -154,8 +153,8 @@ const PinFilesForm = ({ close }: { close: () => void }) => { errors={fields.cids.errors || pinStatus === "error" ? ["An error occurred, please try again"] : []} /> -