portal-dashboard/app/routes/file-manager/index.tsx

163 lines
4.8 KiB
TypeScript
Raw Normal View History

import { GeneralLayout } from "~/components/general-layout";
import { FileCard, FileCardList, FileTypes } from "~/components/file-card";
import { DataTable } from "~/components/data-table";
import { columns } from "./columns";
import { Input } from "~/components/ui/input";
import { Button } from "~/components/ui/button";
import { AddIcon } from "~/components/icons";
2024-03-22 11:31:31 +00:00
import { Authenticated } from "@refinedev/core";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import { TextareaField } from "~/components/forms";
2024-03-22 17:53:39 +00:00
import { z } from "zod";
import { getFormProps, useForm } from "@conform-to/react";
import { getZodConstraint, parseWithZod } from "@conform-to/zod";
import { usePinning } from "~/hooks/usePinning";
import { CID } from "@lumeweb/libs5";
import { useEffect, useState } from "react";
export default function FileManager() {
const [open, setOpen] = useState(false);
const closeModal = () => setOpen(false);
return (
2024-03-22 18:33:30 +00:00
<Authenticated key="file-manager">
<GeneralLayout>
<Dialog open={open} onOpenChange={setOpen}>
2024-03-22 11:31:31 +00:00
<h1 className="font-bold mb-4 text-lg">File Manager</h1>
<FileCardList>
<FileCard
fileName="Backups"
size="33 files"
type={FileTypes.Folder}
createdAt="2 days ago"
/>
<FileCard
fileName="Backups"
size="33 files"
type={FileTypes.Folder}
createdAt="2 days ago"
/>
<FileCard
fileName="Backups"
size="33 files"
type={FileTypes.Folder}
createdAt="2 days ago"
/>
<FileCard
fileName="Backups"
size="33 files"
type={FileTypes.Folder}
createdAt="2 days ago"
/>
</FileCardList>
<h2 className="font-bold text-l mt-8">Files</h2>
<div className="flex items-center space-x-4 my-6 w-full">
<Input
fullWidth
leftIcon={<AddIcon />}
placeholder="Search files by name or CID"
className="border-ring font-medium w-full grow h-12 flex-1 bg-primary-2/10"
/>
{/* We dont yet have any functionality for selecting so im commenting this out */}
{/* <Button className="h-12 gap-x-2">
2024-03-22 11:31:31 +00:00
<AddIcon />
Select All
</Button> */}
2024-03-22 11:31:31 +00:00
<DialogTrigger asChild>
<Button className="h-12 gap-x-2">
<AddIcon />
Pin Content
</Button>
</DialogTrigger>
</div>
<DataTable
columns={columns}
resource="file"
dataProviderName="files"
/>
<DialogContent>
<PinFilesForm close={closeModal} />
</DialogContent>
</Dialog>
</GeneralLayout>
2024-03-22 11:31:31 +00:00
</Authenticated>
);
}
2024-03-22 17:53:39 +00:00
const PinFilesSchema = z.object({
cids: z
.string()
.transform((value) => value.split(","))
.refine(
(value) => {
2024-03-22 23:10:20 +00:00
return value.every((cid) => {
try {
CID.decode(cid);
} catch (e) {
return false;
}
2024-03-22 23:10:20 +00:00
return true;
2024-03-22 23:10:20 +00:00
});
},
(val) => ({
2024-03-22 23:10:20 +00:00
message: `${val} is not a valid CID`,
}),
),
2024-03-22 17:53:39 +00:00
});
const PinFilesForm = ({ close }: { close: () => void }) => {
const { bulkPin, pinStatus, fetchProgress } = usePinning();
2024-03-22 17:53:39 +00:00
const [form, fields] = useForm({
id: "pin-files",
constraint: getZodConstraint(PinFilesSchema),
onValidate({ formData }) {
return parseWithZod(formData, { schema: PinFilesSchema });
},
shouldValidate: "onSubmit",
onSubmit(e, { submission }) {
2024-03-22 18:33:30 +00:00
e.preventDefault();
2024-03-22 17:53:39 +00:00
if (submission?.status === "success") {
const value = submission.value;
bulkPin(value.cids);
}
},
});
useEffect(() => {
if (pinStatus === "success") {
fetchProgress();
close();
}
}, [pinStatus, fetchProgress, close]);
2024-03-22 17:53:39 +00:00
return (
<>
<DialogHeader>
<DialogTitle>Pin Content</DialogTitle>
</DialogHeader>
<form {...getFormProps(form)} className="w-full flex flex-col gap-y-4">
<TextareaField
textareaProps={{
2024-03-22 17:53:39 +00:00
name: fields.cids.name,
placeholder: "Comma separated CIDs",
}}
labelProps={{ htmlFor: "cids", children: "Content to Pin" }}
2024-03-26 14:54:51 +00:00
errors={fields.cids.errors || pinStatus === "error" ? ["An error occurred, please try again"] : []}
2024-03-22 17:53:39 +00:00
/>
<Button type="submit" className="w-full" disabled={pinStatus === "pending"}>
{pinStatus === "pending" ? "Processing..." : "Pin Content"}
2024-03-22 17:53:39 +00:00
</Button>
</form>
</>
);
};