"use client"; import type { ColumnDef, RowSelectionState } from "@tanstack/react-table"; import { CloudUpload, Copy, ExternalLink, HardDriveDownload, Pencil, ReplaceAll, Trash, Trash2, } from "lucide-react"; import { type ChangeEvent, useMemo, useRef, useState } from "react"; import { toast } from "sonner"; import { DataTable } from "@/components/tantable"; import { SimpleTooltip } from "@/components/tooltip"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Textarea } from "@/components/ui/textarea"; import { cdnDelete, cdnify } from "@/lib/api"; import { cn } from "@/lib/utils"; import { fetchToCdn, rename } from "./api"; const columns: ColumnDef<{ id: string; name: string | null; size: string; }>[] = [ { id: "select", header: ({ table }) => ( table.toggleAllPageRowsSelected(!!value)} aria-label="Select all" /> ), cell: ({ row }) => ( row.toggleSelected(!!value)} aria-label="Select row" /> ), enableSorting: false, enableHiding: false, meta: { className: "w-6" }, }, { accessorKey: "name", header: "Name", }, { accessorKey: "id", header: "ID", }, { accessorFn: (row) => b2sClient(Number(row.size)), header: "Size", }, ]; export function CdnTable({ files, onChoose, onChange, }: { files: { id: string; name: string | null; size: string; }[]; onChoose?: ( value: { id: string; name: string | null; size: string; } | null, ) => void; onChange?: () => void; }) { const fileInputRef = useRef(null); const [rowSelection, setRowSelection] = useState({}); const [urls, setUrls] = useState(""); const selectedIds = useMemo( () => Object.entries(rowSelection) .filter((r) => r[1]) .map((r) => files[Number(r[0])].id), [rowSelection, files], ); async function upload(ev: ChangeEvent) { const { files } = ev.target; if (!files) return; for (const file of files) { toast.promise(cdnify(file), { loading: `Uploading ${file.name}...`, success: () => { onChange?.(); return `${file.name} has been uploaded to CDN.`; }, error: `Error uploading ${file.name}.`, }); } } async function deleteSelected() { toast.promise(cdnDelete(selectedIds), { loading: `Delete ${selectedIds.length} files...`, success: (res) => { if (res) { const file = files.find((f) => f.id === res.id); toast.error( `Error deleting ${file ? file.name || `[${res.id}]` : `[${res.id}]`}`, { description: `because it is still being used by ${res.refs.join(", ")}`, }, ); throw ""; } setRowSelection({}); onChange?.(); return `${selectedIds.length} files has been deleted.`; }, error: `Error deleting the files.`, }); } async function fetchUrls() { const urlList: string[] = urls .toString() .split("\n") .filter((u) => u); if (!urlList.length) return; toast.promise(fetchToCdn(urlList), { loading: `Fetching ${urlList.length} files...`, success: () => { onChange?.(); return `${urlList.length} URLs has been uploaded to CDN.`; }, error: "Error fetching the files.", }); } return (
[ { label: "เปิดในแท็บใหม่", icon: , onClick() { open(`/cdn/${row.id}`); }, }, { label: "ก็อปลิ้งค์", icon: , onClick() { toast.promise( navigator.clipboard.writeText( new URL(`/cdn/${row.id}`, location.href).href, ), { success() { return "ก็อปลิ้งค์สำเร็จ"; }, error() { return "เกิดข้อผิดพลาดขณะก็อปลิ้งค์"; }, }, ); }, }, { label: "เปลี่ยนชื่อ", icon: , onClick() { const newName = prompt("ชื่อไฟล์ใหม่", row.name ?? undefined); if (!newName) return; toast.promise(rename(row.id, newName), { success() { onChange?.(); return "เปลี่ยนชื่อสำเร็จ"; }, error() { return "เกิดข้อผิดพลาดขณะเปลี่ยนชื่อ"; }, }); }, }, { label: "ลบไฟล์", icon: , onClick() { toast.promise(cdnDelete([row.id]), { success(res) { if (res) { const file = files.find((f) => f.id === res.id); throw `${file ? file.name || `[${res.id}]` : `[${res.id}]`} ยังถูกใช้โดย ${res.refs.join(", ")}`; } onChange?.(); return "ลบสำเร็จ"; }, error(err: { message: string; description: string }) { if (typeof err === "string") return err; return "เกิดข้อผิดพลาดขณะลบ"; }, }); }, }, ]} onClick={(row) => onChoose?.(row)} />
Fetch From URLs Enter URLs to be fetched and added to CDN below. One URL per line.