implemented basic support for pdf, png and jpg

This commit is contained in:
daniel31x13
2023-12-03 23:52:32 -05:00
parent 33be9e5d83
commit 9c65e3e215
16 changed files with 443 additions and 69 deletions
@@ -64,10 +64,12 @@ export default function DeleteCollectionModal({
return (
<Modal toggleModal={onClose}>
<p className="text-xl mb-5 font-thin text-red-500">
<p className="text-xl font-thin text-red-500">
{permissions === true ? "Delete" : "Leave"} Collection
</p>
<div className="divider my-3"></div>
<div className="flex flex-col gap-3">
{permissions === true ? (
<>
+4 -9
View File
@@ -21,14 +21,6 @@ export default function DeleteLinkModal({ onClose, activeLink }: Props) {
const [link, setLink] =
useState<LinkIncludingShortenedCollectionAndTags>(activeLink);
let shortendURL;
try {
shortendURL = new URL(link.url).host.toLowerCase();
} catch (error) {
console.log(error);
}
const { removeLink } = useLinkStore();
const [submitLoader, setSubmitLoader] = useState(false);
@@ -50,7 +42,10 @@ export default function DeleteLinkModal({ onClose, activeLink }: Props) {
return (
<Modal toggleModal={onClose}>
<p className="text-xl mb-5 font-thin text-red-500">Delete Link</p>
<p className="text-xl font-thin text-red-500">Delete Link</p>
<div className="divider my-3"></div>
<div className="flex flex-col gap-3">
<p>Are you sure you want to delete this Link?</p>
@@ -49,7 +49,9 @@ export default function EditCollectionModal({
return (
<Modal toggleModal={onClose}>
<p className="text-xl mb-5 font-thin">Edit Collection Info</p>
<p className="text-xl font-thin">Edit Collection Info</p>
<div className="divider my-3"></div>
<div className="flex flex-col gap-3">
<div className="flex flex-col sm:flex-row gap-3">
@@ -95,10 +95,12 @@ export default function EditCollectionSharingModal({
return (
<Modal toggleModal={onClose}>
<p className="text-xl font-thin mb-5">
<p className="text-xl font-thin">
{permissions === true ? "Share and Collaborate" : "Team"}
</p>
<div className="divider my-3"></div>
<div className="flex flex-col gap-3">
{permissions === true && (
<div>
@@ -178,7 +180,7 @@ export default function EditCollectionSharingModal({
setMemberState
)
}
className="btn btn-primary text-white btn-square"
className="btn btn-primary btn-square btn-sm h-10 w-10"
>
<FontAwesomeIcon icon={faUserPlus} className="w-5 h-5" />
</div>
@@ -323,7 +325,7 @@ export default function EditCollectionSharingModal({
}}
/>
<span
className={`peer-checked:bg-primary text-sm ${
className={`peer-checked:bg-primary peer-checked:text-primary-content text-sm ${
permissions === true
? "hover:bg-neutral-content duration-100"
: ""
@@ -368,7 +370,7 @@ export default function EditCollectionSharingModal({
}}
/>
<span
className={`peer-checked:bg-primary text-sm ${
className={`peer-checked:bg-primary peer-checked:text-primary-content text-sm ${
permissions === true
? "hover:bg-neutral-content duration-100"
: ""
@@ -413,7 +415,7 @@ export default function EditCollectionSharingModal({
}}
/>
<span
className={`peer-checked:bg-primary text-sm ${
className={`peer-checked:bg-primary peer-checked:text-primary-content text-sm ${
permissions === true
? "hover:bg-neutral-content duration-100"
: ""
+18 -14
View File
@@ -24,7 +24,7 @@ export default function EditLinkModal({ onClose, activeLink }: Props) {
let shortendURL;
try {
shortendURL = new URL(link.url).host.toLowerCase();
shortendURL = new URL(link.url || "").host.toLowerCase();
} catch (error) {
console.log(error);
}
@@ -78,20 +78,24 @@ export default function EditLinkModal({ onClose, activeLink }: Props) {
return (
<Modal toggleModal={onClose}>
<p className="text-xl mb-5 font-thin">Edit Link</p>
<p className="text-xl font-thin">Edit Link</p>
<Link
href={link.url}
className="truncate text-neutral flex gap-2 mb-5 w-fit max-w-full"
title={link.url}
target="_blank"
>
<FontAwesomeIcon
icon={faLink}
className="mt-1 w-5 h-5 min-w-[1.25rem]"
/>
<p>{shortendURL}</p>
</Link>
<div className="divider my-3"></div>
{link.url ? (
<Link
href={link.url}
className="truncate text-neutral flex gap-2 mb-5 w-fit max-w-full"
title={link.url}
target="_blank"
>
<FontAwesomeIcon
icon={faLink}
className="mt-1 w-5 h-5 min-w-[1.25rem]"
/>
<p>{shortendURL}</p>
</Link>
) : undefined}
<div className="w-full">
<p className="mb-2">Name</p>
@@ -54,7 +54,9 @@ export default function NewCollectionModal({ onClose }: Props) {
return (
<Modal toggleModal={onClose}>
<p className="text-xl mb-5 font-thin">Create a New Collection</p>
<p className="text-xl font-thin">Create a New Collection</p>
<div className="divider my-3"></div>
<div className="flex flex-col gap-3">
<div className="flex flex-col sm:flex-row gap-3">
+4 -7
View File
@@ -41,8 +41,6 @@ export default function NewLinkModal({ onClose }: Props) {
const { addLink } = useLinkStore();
const [submitLoader, setSubmitLoader] = useState(false);
const [resetCollectionSelection, setResetCollectionSelection] = useState("");
const [optionsExpanded, setOptionsExpanded] = useState(false);
const router = useRouter();
@@ -66,9 +64,6 @@ export default function NewLinkModal({ onClose }: Props) {
};
useEffect(() => {
setResetCollectionSelection(Date.now().toString());
console.log(link);
setOptionsExpanded(false);
if (router.query.id) {
const currentCollection = collections.find(
@@ -123,7 +118,10 @@ export default function NewLinkModal({ onClose }: Props) {
return (
<Modal toggleModal={onClose}>
<p className="text-xl mb-5 font-thin">Create a New Link</p>
<p className="text-xl font-thin">Create a New Link</p>
<div className="divider my-3"></div>
<div className="grid grid-flow-row-dense sm:grid-cols-5 gap-3">
<div className="sm:col-span-3 col-span-5">
<p className="mb-2">Link</p>
@@ -143,7 +141,6 @@ export default function NewLinkModal({ onClose }: Props) {
label: link.collection.name,
value: link.collection.id,
}}
id={resetCollectionSelection}
/>
) : null}
</div>
+237
View File
@@ -0,0 +1,237 @@
import React, { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import CollectionSelection from "@/components/InputSelect/CollectionSelection";
import TagSelection from "@/components/InputSelect/TagSelection";
import TextInput from "@/components/TextInput";
import unescapeString from "@/lib/client/unescapeString";
import useCollectionStore from "@/store/collections";
import useLinkStore from "@/store/links";
import {
ArchivedFormat,
LinkIncludingShortenedCollectionAndTags,
} from "@/types/global";
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";
import toast from "react-hot-toast";
import Modal from "../Modal";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQuestion } from "@fortawesome/free-solid-svg-icons";
import { faQuestionCircle } from "@fortawesome/free-regular-svg-icons";
type Props = {
onClose: Function;
};
export default function UploadFileModal({ onClose }: Props) {
const { data } = useSession();
const initial = {
name: "",
url: "",
description: "",
type: "url",
tags: [],
screenshotPath: "",
pdfPath: "",
readabilityPath: "",
textContent: "",
collection: {
name: "",
ownerId: data?.user.id as number,
},
} as LinkIncludingShortenedCollectionAndTags;
const [link, setLink] =
useState<LinkIncludingShortenedCollectionAndTags>(initial);
const [file, setFile] = useState<File>();
const { addLink } = useLinkStore();
const [submitLoader, setSubmitLoader] = useState(false);
const [optionsExpanded, setOptionsExpanded] = useState(false);
const router = useRouter();
const { collections } = useCollectionStore();
const setCollection = (e: any) => {
if (e?.__isNew__) e.value = null;
setLink({
...link,
collection: { id: e?.value, name: e?.label, ownerId: e?.ownerId },
});
};
const setTags = (e: any) => {
const tagNames = e.map((e: any) => {
return { name: e.label };
});
setLink({ ...link, tags: tagNames });
};
useEffect(() => {
setOptionsExpanded(false);
if (router.query.id) {
const currentCollection = collections.find(
(e) => e.id == Number(router.query.id)
);
if (
currentCollection &&
currentCollection.ownerId &&
router.asPath.startsWith("/collections/")
)
setLink({
...initial,
collection: {
id: currentCollection.id,
name: currentCollection.name,
ownerId: currentCollection.ownerId,
},
});
} else
setLink({
...initial,
collection: {
name: "Unorganized",
ownerId: data?.user.id as number,
},
});
}, []);
const submit = async () => {
if (!submitLoader && file) {
let fileType: ArchivedFormat | null = null;
if (file?.type === "image/jpg" || file.type === "image/jpeg")
fileType = ArchivedFormat.jpeg;
else if (file.type === "image/png") fileType = ArchivedFormat.png;
else if (file.type === "application/pdf") fileType = ArchivedFormat.pdf;
console.log(fileType);
if (fileType !== null) {
setSubmitLoader(true);
let response;
const load = toast.loading("Creating...");
response = await addLink(link);
toast.dismiss(load);
if (response.ok) {
const formBody = new FormData();
file && formBody.append("file", file);
console.log(formBody.get("file"));
await fetch(
`/api/v1/archives/${
(response.data as LinkIncludingShortenedCollectionAndTags).id
}?format=${fileType}`,
{
body: formBody,
method: "POST",
}
);
toast.success(`Created!`);
onClose();
} else toast.error(response.data as string);
setSubmitLoader(false);
return response;
}
}
};
return (
<Modal toggleModal={onClose}>
<div className="flex gap-2 items-start">
<p className="text-xl font-thin">Upload File</p>
</div>
<div className="divider my-3"></div>
<div className="grid grid-flow-row-dense sm:grid-cols-5 gap-3">
<div className="sm:col-span-3 col-span-5">
<p className="mb-2">File</p>
<label className="btn h-10 btn-sm w-full border border-neutral-content hover:border-neutral-content flex justify-between">
<input
type="file"
accept=".pdf,.png,.jpg,.jpeg"
className="cursor-pointer custom-file-input"
onChange={(e) => e.target.files && setFile(e.target.files[0])}
/>
</label>
<p className="text-xs font-semibold mt-2">
PDF, PNG, JPG (Up to {process.env.NEXT_PUBLIC_MAX_UPLOAD_SIZE || 30}
MB)
</p>
</div>
<div className="sm:col-span-2 col-span-5">
<p className="mb-2">Collection</p>
{link.collection.name ? (
<CollectionSelection
onChange={setCollection}
defaultValue={{
label: link.collection.name,
value: link.collection.id,
}}
/>
) : null}
</div>
</div>
{optionsExpanded ? (
<div className="mt-5">
{/* <hr className="mb-3 border border-neutral-content" /> */}
<div className="grid sm:grid-cols-2 gap-3">
<div>
<p className="mb-2">Name</p>
<TextInput
value={link.name}
onChange={(e) => setLink({ ...link, name: e.target.value })}
placeholder="e.g. Example Link"
className="bg-base-200"
/>
</div>
<div>
<p className="mb-2">Tags</p>
<TagSelection
onChange={setTags}
defaultValue={link.tags.map((e) => {
return { label: e.name, value: e.id };
})}
/>
</div>
<div className="sm:col-span-2">
<p className="mb-2">Description</p>
<textarea
value={unescapeString(link.description) as string}
onChange={(e) =>
setLink({ ...link, description: e.target.value })
}
placeholder="Will be auto generated if nothing is provided."
className="resize-none w-full rounded-md p-2 border-neutral-content bg-base-200 focus:border-sky-300 dark:focus:border-sky-600 border-solid border outline-none duration-100"
/>
</div>
</div>
</div>
) : undefined}
<div className="flex justify-between items-center mt-5">
<div
onClick={() => setOptionsExpanded(!optionsExpanded)}
className={`rounded-md cursor-pointer btn btn-sm btn-ghost duration-100 flex items-center px-2 w-fit text-sm`}
>
<p>{optionsExpanded ? "Hide" : "More"} Options</p>
</div>
<button className="btn btn-accent" onClick={submit}>
Create Link
</button>
</div>
</Modal>
);
}