Skip to content

Commit

Permalink
feat: add UI option for viewing file metadata (#108)
Browse files Browse the repository at this point in the history
* refactor: move SetAtom type to separate file

* chore: fix toasts

* feat: add dialog trigger for metadata modal

* chore: add missing dependency for useEffect

* chore(ui): add filemetadata type

* feat: add file-data-modal
  • Loading branch information
kevinanielsen authored Jan 25, 2024
1 parent d923d0a commit 9982727
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 21 deletions.
10 changes: 5 additions & 5 deletions ui/src/actions/getFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import axios from "axios";
import { SetStateAction } from "jotai";
import toast from "react-hot-toast";
import File from "../types/file";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type SetAtom<Args extends any[], Result> = (...args: Args) => Result;
import { SetAtom } from "@/types/setAtom";

export const getFiles = (
type: "images" | "documents",
Expand All @@ -13,12 +11,14 @@ export const getFiles = (
toast.loading("Loading files...");
axios
.get(`/api/cdn/${type === "images" ? "image" : "doc"}/all`)
.then((res) => res.data != null && setFiles(res.data))
.then((res) => {
res.data != null && setFiles(res.data)
toast.dismiss();
})
.catch((err: Error) => {
toast.dismiss();
toast.error(err.message);
console.log(err);
})
.finally(() => toast.dismiss());
}

33 changes: 18 additions & 15 deletions ui/src/components/content-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { filesAtom, sizeAtom } from "../store";
import { getSize } from "../actions/getSize";
import RenameModal from "./rename-modal";
import { Button } from "./ui/button";
import { Dialog, DialogTrigger } from "./ui/dialog";
import FileDataModal from "./file-data-modal";

type TContentCardProps = {
file_name?: string;
Expand Down Expand Up @@ -56,17 +58,22 @@ const ContentCard: React.FC<TContentCardProps> = ({

return (
<div className="border rounded-lg shadow-lg flex flex-col min-h-[264px] w-64 max-w-[256px] justify-between items-center gap-4 p-4">
{type === "images" ? (
<img
src={url}
alt={file_name}
width={224}
height={150}
className="object-cover max-h-[150px] max-w-[224px]"
/>
) : (
<FileText size="128" />
)}
<Dialog>
<DialogTrigger>
{type === "images" ? (
<img
src={url}
alt={file_name}
width={224}
height={150}
className="object-cover max-h-[150px] max-w-[224px]"
/>
) : (
<FileText size="128" />
)}
</DialogTrigger>
<FileDataModal filename={file_name} type={type} />
</Dialog>
<div className="w-full flex flex-col">
<p className="truncate w-64 pr-7">{file_name}</p>
{/* Non-destructive buttons */}
Expand All @@ -81,14 +88,12 @@ const ContentCard: React.FC<TContentCardProps> = ({
toast.success("clipboard saved");
}}
aria-label="Copy Link"
aria-labelledby="Copy Link"
>
<Files className="inline" size="24" />
</Button>
<a
className="hover:bg-accent hover:text-accent-foreground h-10 w-10 inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 text-sky-600"
aria-label="Download file"
aria-labelledby="Download file"
href={url}
download
>
Expand All @@ -101,10 +106,8 @@ const ContentCard: React.FC<TContentCardProps> = ({
<Button
variant="destructive"
size="icon"
className=""
onClick={() => file_name && deleteFile()}
aria-label="Delete file"
aria-labelledby="Delete file"
>
<Trash2 className="inline" size="24" />
</Button>
Expand Down
81 changes: 81 additions & 0 deletions ui/src/components/file-data-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { useEffect, useState } from "react";
import { DialogContent, DialogHeader, DialogTitle } from "./ui/dialog";
import axios from "axios";
import toast from "react-hot-toast";
import { FileMetadata } from "@/types/fileMetadata";
import Seperator from "./seperator";

type TFileDataModalProps = {
filename?: string;
type?: "images" | "documents";
};

const FileDataModal: React.FC<TFileDataModalProps> = ({ filename, type }) => {
const [data, setData] = useState<FileMetadata>();
useEffect(() => {
if (filename && type) {
axios
.get<FileMetadata>(
`/api/cdn/${type === "documents" ? "doc" : "image"}/${filename}`
)
.then((res) => {
toast.dismiss();
if (res.status === 200) {
setData(res.data);
}
})
.catch((err) => {
toast.dismiss();
toast.error(err.message);
});
}
axios;
}, [filename, type]);
if (!data)
return (
<DialogContent className="overflow-hidden">
<DialogHeader>
<DialogTitle>{filename}</DialogTitle>
</DialogHeader>
Error fetching file data.
</DialogContent>
);
return (
<DialogContent className="overflow-clip">
<DialogHeader className="w-[90%]">
<DialogTitle className="truncate">{filename}</DialogTitle>
<Seperator />
</DialogHeader>

<div className="">
<strong>Filename</strong>
<p id="filename">{data.filename}</p>
</div>
<div className="">
<strong>File Size</strong>
<p id="filename">
{data.file_size < 1000 && `${data.file_size} b`}
{999999 > data.file_size && data.file_size >= 1000 && `${Math.round(data.file_size / 100) / 10} KB`}
{1000000000 > data.file_size &&
data.file_size >= 1000000 &&
`${Math.round(data.file_size / 100000) / 10} MB`}
{1000000000000 > data.file_size &&
data.file_size >= 1000000000 &&
`${Math.round(data.file_size / 100000000) / 10} GB`}
{data.file_size >= 1000000000000 &&
`${Math.round(data.file_size / 100000000000) / 10} TB`}
</p>
</div>
{type === "images" && (
<div className="">
<strong>Dimensions</strong>
<p id="filename">Height: {data.height}px</p>
<p id="filename">Width: {data.width}px</p>
</div>

)}
</DialogContent>
);
};

export default FileDataModal;
2 changes: 1 addition & 1 deletion ui/src/components/files.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const Files: React.FC<TFilesProps> = ({ type }) => {

useEffect(() => {
getFiles(type, setFiles)
}, [type]);
}, [type, setFiles]);

return (
<div className="w-full">
Expand Down
7 changes: 7 additions & 0 deletions ui/src/types/fileMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type FileMetadata = {
download_url: string;
file_size: number;
filename: string;
height?: number;
width?: number;
};
2 changes: 2 additions & 0 deletions ui/src/types/setAtom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type SetAtom<Args extends any[], Result> = (...args: Args) => Result;

0 comments on commit 9982727

Please sign in to comment.