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 (
<>
Drag & Drop Files or Browse
+ > ); }; 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