Skip to content

Commit

Permalink
Vault
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusab committed Dec 16, 2023
1 parent 57af56a commit 13eaf55
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 22 deletions.
21 changes: 12 additions & 9 deletions apps/dashboard/src/components/attachments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ import { cn } from "@midday/ui/utils";
import { X } from "lucide-react";
import { useEffect, useState } from "react";
import { useDropzone } from "react-dropzone";
import { FilePreview } from "./file-preview";

const Item = ({ file, onDelete, id }) => {
return (
<div className="flex items-center justify-between">
<div className="flex space-x-4 items-center">
<HoverCard openDelay={300}>
<HoverCard openDelay={200}>
<HoverCardTrigger>
<div className="rounded-md border w-[40px] h-[40px] flex items-center justify-center overflow-hidden cursor-pointer">
<iframe
src={`/api/proxy?filePath=vault/${file.path}#toolbar=0`}
title={file.name}
className="w-[40px] h-[40px] pointer-none"
<FilePreview
src={`/api/proxy?filePath=vault/${file.path}`}
className="w-[40px] h-[40px]"
name={file.name}
type={file.type}
preview
/>
</div>
</HoverCardTrigger>
Expand All @@ -36,10 +39,10 @@ const Item = ({ file, onDelete, id }) => {
side="left"
sideOffset={55}
>
<iframe
src={`/api/proxy?filePath=vault/${file.path}#toolbar=0`}
title={file.name}
className="w-80 h-full"
<FilePreview
src={`/api/proxy?filePath=vault/${file.path}`}
name={file.name}
type={file.type}
/>
</HoverCardContent>
</HoverCard>
Expand Down
136 changes: 136 additions & 0 deletions apps/dashboard/src/components/file-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
"use client";

import { Button } from "@midday/ui/button";
import { Icons } from "@midday/ui/icons";
import { Skeleton } from "@midday/ui/skeleton";
import { cn } from "@midday/ui/utils";
import { AnimatePresence, motion } from "framer-motion";
import { useState } from "react";

enum FileType {
Pdf = "application/pdf",
Heic = "image/heic",
}

type Props = {
type: FileType;
name: string;
className?: string;
preview?: boolean;
src: string;
};

export const isSupportedFilePreview = (type: FileType) => {
if (!type) {
return false;
}

if (type === FileType.Heic) {
return false;
}

if (type?.startsWith("image")) {
return true;
}

switch (type) {
case FileType.Pdf:
return true;

default:
return false;
}
};

export function FilePreview({ src, className, name, type, preview }: Props) {
const [isLoaded, setLoaded] = useState(false);

const handleOnLoaded = () => {
setTimeout(() => {
setLoaded(true);
}, 150);
};

let content;

if (type?.startsWith("image")) {
content = (
<div
className={cn(
"flex items-center justify-center w-[300px] h-[315px]",
className
)}
>
<img
src={src}
className="object-contain"
alt={name}
onLoad={handleOnLoaded}
/>
</div>
);
}

if (type === FileType.Pdf) {
content = (
<div className={cn("overflow-hidden w-[300px] h-[317px]", className)}>
<iframe
src={`${src}#toolbar=0`}
className={cn("-ml-[3px] -mt-[3px] w-[305px] h-[327px]", className)}
title={name}
onLoad={handleOnLoaded}
/>
</div>
);
}

return (
<div className={cn(className, "relative")}>
{!preview && isLoaded && (
<AnimatePresence>
<div className="absolute bottom-2 left-2 flex space-x-2">
<motion.div
initial={{ y: 50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: -50, opacity: 0 }}
>
<Button
variant="secondary"
className="w-[32px] h-[32px] bg-black/60 hover:bg-black"
size="icon"
>
<Icons.OpenInFull />
</Button>
</motion.div>
<motion.div
initial={{ y: 50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: -50, opacity: 0 }}
transition={{ delay: 0.04 }}
>
<Button
variant="secondary"
className="w-[32px] h-[32px] bg-black/60 hover:bg-black"
size="icon"
>
<Icons.FileDownload />
</Button>
</motion.div>
</div>
</AnimatePresence>
)}

<Skeleton
className={cn(
"absolute top-0 left-0 z-50 pointer-events-none w-full h-full",
isLoaded && "hidden"
)}
/>
<div
className={cn("bg-primary/10 w-full h-full", !isLoaded && "opacity-0")}
>
{content}
</div>
</div>
);
}
19 changes: 10 additions & 9 deletions apps/dashboard/src/components/tables/vault/data-table-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { deleteFileAction } from "@/actions/delete-file-action";
import { deleteFolderAction } from "@/actions/delete-folder-action";
import { shareFileAction } from "@/actions/share-file-action";
import { FileIcon } from "@/components/file-icon";
import { FilePreview, isSupportedFilePreview } from "@/components/file-preview";
import { useI18n } from "@/locales/client";
import { useVaultContext } from "@/store/vault/hook";
import { formatSize } from "@/utils/format";
Expand Down Expand Up @@ -178,16 +179,16 @@ export function DataTableRow({ data, teamId }) {
},
});

const filePreviewSupported = isSupportedFilePreview(data?.metadata?.mimetype);

return (
<AlertDialog>
<ContextMenu>
<ContextMenuTrigger asChild>
<TableRow className="h-[45px] cursor-default">
<TableCell>
<HoverCard openDelay={300}>
<HoverCardTrigger
disabled={data?.metadata?.mimetype !== "application/pdf"}
>
<HoverCard openDelay={200}>
<HoverCardTrigger>
<div className="flex items-center space-x-2">
<FileIcon
mimetype={data?.metadata?.mimetype}
Expand All @@ -209,12 +210,12 @@ export function DataTableRow({ data, teamId }) {
)}
</div>
</HoverCardTrigger>
{data?.metadata?.mimetype === "application/pdf" && (
{filePreviewSupported && (
<HoverCardContent className="w-70 h-[350px]">
<iframe
src={`/api/proxy?filePath=vault/${teamId}/${filepath}#toolbar=0`}
title={data.name}
className="w-80 h-full"
<FilePreview
src={`/api/proxy?filePath=vault/${teamId}/${filepath}`}
name={data.name}
type={data?.metadata?.mimetype}
/>
</HoverCardContent>
)}
Expand Down
1 change: 0 additions & 1 deletion packages/supabase/src/queries/cached-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ export const getVault = async (params) => {
["vault", teamId],
{
tags: [`vault_${teamId}`],
revalidate: 10,
}
)(params);
};
6 changes: 3 additions & 3 deletions packages/supabase/src/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ export async function getTransactionsQuery(
*,
assigned:assigned_id(*),
enrichment:enrichment_id(category),
attachments(id,size,name,path)
attachments(*)
`,
{ count: "exact" }
)
Expand Down Expand Up @@ -318,7 +318,7 @@ export async function getTransactionQuery(supabase: Client, id: string) {
*,
assigned:assigned_id(*),
enrichment:enrichment_id(category),
attachments(id,size,name,path)
attachments(*)
`
)
.eq("id", id)
Expand Down Expand Up @@ -491,7 +491,6 @@ export async function getVaultQuery(supabase: Client, params: GetVaultParams) {
: [
{ name: "inbox", isFolder: true },
{ name: "exports", isFolder: true },
{ name: "transactions", isFolder: true },
];

let basePath = teamId;
Expand All @@ -507,6 +506,7 @@ export async function getVaultQuery(supabase: Client, params: GetVaultParams) {
const filteredData =
data
?.filter((file) => file.name !== EMPTY_FOLDER_PLACEHOLDER_FILE_NAME)
.filter((file) => file.name !== "transactions")
.map((item) => ({ ...item, isFolder: !item.id })) ?? [];

const mergedMap = new Map(
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ import {
MdOutlineCategory,
MdOutlineDescription,
MdOutlineDifference,
MdOutlineFileDownload,
MdOutlineIntegrationInstructions,
MdOutlineInventory2,
MdOutlineListAlt,
MdOutlineNotificationsNone,
MdOutlineOpenInFull,
MdOutlineTune,
MdPayments,
MdPeople,
Expand Down Expand Up @@ -413,4 +415,6 @@ export const Icons = {
Search: MdSearch,
CreateNewFolder: MdCreateNewFolder,
Error: MdErrorOutline,
OpenInFull: MdOutlineOpenInFull,
FileDownload: MdOutlineFileDownload,
};

0 comments on commit 13eaf55

Please sign in to comment.