diff --git a/components/LinkPreview.tsx b/components/LinkPreview.tsx deleted file mode 100644 index 891a69f7..00000000 --- a/components/LinkPreview.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { faFolder, faLink } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import Image from "next/image"; -import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; -import isValidUrl from "@/lib/shared/isValidUrl"; -import A from "next/link"; -import unescapeString from "@/lib/client/unescapeString"; -import { Link } from "@prisma/client"; - -type Props = { - link?: Partial; - className?: string; - settings: { - blurredFavicons: boolean; - displayLinkIcons: boolean; - }; -}; - -export default function LinkPreview({ link, className, settings }: Props) { - if (!link) { - link = { - name: "Linkwarden", - url: "https://linkwarden.app", - createdAt: Date.now() as unknown as Date, - }; - } - - let shortendURL; - - try { - shortendURL = new URL(link.url as string).host.toLowerCase(); - } catch (error) { - console.log(error); - } - - const url = isValidUrl(link.url as string) - ? new URL(link.url as string) - : undefined; - - const formattedDate = new Date(link.createdAt as Date).toLocaleString( - "en-US", - { - year: "numeric", - month: "short", - day: "numeric", - } - ); - - return ( - <> -
-
- {url && settings?.displayLinkIcons && ( - { - const target = e.target as HTMLElement; - target.style.display = "none"; - }} - /> - )} - -
-
-
-

{1}

-

- {unescapeString(link.name as string)} -

-
-
- -

Landing Pages ⚡️

-
- { - e.stopPropagation(); - }} - className="flex items-center gap-1 max-w-full w-fit text-neutral hover:opacity-70 duration-100" - > - -

{shortendURL}

-
-
- -

{formattedDate}

-
-
-
-
-
- - ); -} diff --git a/components/LinkSidebar.tsx b/components/LinkSidebar.tsx deleted file mode 100644 index f3136f43..00000000 --- a/components/LinkSidebar.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faPen, - faBoxesStacked, - faTrashCan, -} from "@fortawesome/free-solid-svg-icons"; -import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; -import useModalStore from "@/store/modals"; -import useLinkStore from "@/store/links"; -import { - CollectionIncludingMembersAndLinkCount, - LinkIncludingShortenedCollectionAndTags, -} from "@/types/global"; -import { useSession } from "next-auth/react"; -import useCollectionStore from "@/store/collections"; - -type Props = { - className?: string; - onClick?: Function; -}; - -export default function LinkSidebar({ className, onClick }: Props) { - const session = useSession(); - const userId = session.data?.user.id; - - const { setModal } = useModalStore(); - - const { links, removeLink } = useLinkStore(); - const { collections } = useCollectionStore(); - - const [linkCollection, setLinkCollection] = - useState(); - - const [link, setLink] = useState(); - - const router = useRouter(); - - useEffect(() => { - if (links) setLink(links.find((e) => e.id === Number(router.query.id))); - }, [links]); - - useEffect(() => { - if (link) - setLinkCollection(collections.find((e) => e.id === link?.collection?.id)); - }, [link]); - - return ( -
-
- {link?.collection.ownerId === userId || - linkCollection?.members.some( - (e) => e.userId === userId && e.canUpdate - ) ? ( -
{ - link - ? setModal({ - modal: "LINK", - state: true, - active: link, - method: "UPDATE", - }) - : undefined; - onClick && onClick(); - }} - className={`hover:opacity-60 duration-100 py-2 px-2 cursor-pointer flex items-center gap-4 w-full rounded-md h-8`} - > - - -

Edit

-
- ) : undefined} - -
{ - link - ? setModal({ - modal: "LINK", - state: true, - active: link, - method: "FORMATS", - }) - : undefined; - onClick && onClick(); - }} - title="Preserved Formats" - className={`hover:opacity-60 duration-100 py-2 px-2 cursor-pointer flex items-center gap-4 w-full rounded-md h-8`} - > - - -

Preserved Formats

-
- - {link?.collection.ownerId === userId || - linkCollection?.members.some( - (e) => e.userId === userId && e.canDelete - ) ? ( -
{ - if (link?.id) { - removeLink(link.id); - router.back(); - onClick && onClick(); - } - }} - title="Delete" - className={`hover:opacity-60 duration-100 py-2 px-2 cursor-pointer flex items-center gap-4 w-full rounded-md h-8`} - > - - -

Delete

-
- ) : undefined} -
-
- ); -} diff --git a/components/Modal/Collection/CollectionInfo.tsx b/components/Modal/Collection/CollectionInfo.tsx index 635bdd4f..be33707c 100644 --- a/components/Modal/Collection/CollectionInfo.tsx +++ b/components/Modal/Collection/CollectionInfo.tsx @@ -1,14 +1,8 @@ import { Dispatch, SetStateAction, useState } from "react"; -import { - faFolder, - faPenToSquare, - faPlus, -} from "@fortawesome/free-solid-svg-icons"; import useCollectionStore from "@/store/collections"; import { CollectionIncludingMembersAndLinkCount } from "@/types/global"; import SubmitButton from "@/components/SubmitButton"; import { HexColorPicker } from "react-colorful"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { toast } from "react-hot-toast"; import TextInput from "@/components/TextInput"; @@ -73,10 +67,7 @@ export default function CollectionInfo({

Color

- +
diff --git a/components/Modal/Collection/DeleteCollection.tsx b/components/Modal/Collection/DeleteCollection.tsx index caadfa4d..472b6aa5 100644 --- a/components/Modal/Collection/DeleteCollection.tsx +++ b/components/Modal/Collection/DeleteCollection.tsx @@ -1,9 +1,4 @@ import React, { useState } from "react"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faRightFromBracket, - faTrashCan, -} from "@fortawesome/free-solid-svg-icons"; import { CollectionIncludingMembersAndLinkCount } from "@/types/global"; import useCollectionStore from "@/store/collections"; import { useRouter } from "next/router"; @@ -111,10 +106,7 @@ export default function DeleteCollection({ }`} onClick={submit} > - + {permissions === true ? "Delete" : "Leave"} Collection
diff --git a/components/Modal/Collection/TeamManagement.tsx b/components/Modal/Collection/TeamManagement.tsx index 9736c4e8..e04b3c85 100644 --- a/components/Modal/Collection/TeamManagement.tsx +++ b/components/Modal/Collection/TeamManagement.tsx @@ -1,12 +1,4 @@ -import { Dispatch, SetStateAction, useEffect, useState } from "react"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faClose, - faCrown, - faPenToSquare, - faPlus, - faUserPlus, -} from "@fortawesome/free-solid-svg-icons"; +import React, { Dispatch, SetStateAction, useEffect, useState } from "react"; import useCollectionStore from "@/store/collections"; import { CollectionIncludingMembersAndLinkCount, Member } from "@/types/global"; import addMemberToCollection from "@/lib/client/addMemberToCollection"; @@ -173,7 +165,7 @@ export default function TeamManagement({ } className="flex items-center justify-center bg-sky-700 hover:bg-sky-600 duration-100 text-white w-10 h-10 p-2 rounded-md cursor-pointer" > - + @@ -194,9 +186,8 @@ export default function TeamManagement({ className="relative border p-2 rounded-md border-neutral flex flex-col sm:flex-row sm:items-center gap-2 justify-between" > {permissions === true && ( - { const updatedMembers = collection.members.filter( @@ -402,10 +393,6 @@ export default function TeamManagement({

{collectionOwner.name}

-

@{collectionOwner.username}

@@ -422,7 +409,6 @@ export default function TeamManagement({ onClick={submit} loading={submitLoader} label={method === "CREATE" ? "Add" : "Save"} - icon={method === "CREATE" ? faPlus : faPenToSquare} className="mx-auto mt-2" /> )} diff --git a/components/Modal/Collection/ViewTeam.tsx b/components/Modal/Collection/ViewTeam.tsx index 4896efd4..f54f542a 100644 --- a/components/Modal/Collection/ViewTeam.tsx +++ b/components/Modal/Collection/ViewTeam.tsx @@ -1,6 +1,4 @@ import { useEffect, useState } from "react"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faCrown } from "@fortawesome/free-solid-svg-icons"; import { CollectionIncludingMembersAndLinkCount } from "@/types/global"; import ProfilePhoto from "@/components/ProfilePhoto"; import getPublicUserData from "@/lib/client/getPublicUserData"; @@ -45,10 +43,6 @@ export default function ViewTeam({ collection }: Props) {

{collectionOwner.name}

- Admin
diff --git a/components/Modal/Link/AddOrEditLink.tsx b/components/Modal/Link/AddOrEditLink.tsx index 23a69860..8b17f311 100644 --- a/components/Modal/Link/AddOrEditLink.tsx +++ b/components/Modal/Link/AddOrEditLink.tsx @@ -2,9 +2,7 @@ import React, { useEffect, useState } from "react"; import CollectionSelection from "@/components/InputSelect/CollectionSelection"; import TagSelection from "@/components/InputSelect/TagSelection"; import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; -import { faPenToSquare } from "@fortawesome/free-regular-svg-icons"; import useLinkStore from "@/store/links"; -import { faLink, faPlus } from "@fortawesome/free-solid-svg-icons"; import { useSession } from "next-auth/react"; import useCollectionStore from "@/store/collections"; import { useRouter } from "next/router"; @@ -13,7 +11,6 @@ import { toast } from "react-hot-toast"; import Link from "next/link"; import TextInput from "@/components/TextInput"; import unescapeString from "@/lib/client/unescapeString"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; type Props = | { @@ -142,7 +139,7 @@ export default function AddOrEditLink({ className="text-neutral break-all w-full flex gap-2" title={link.url || ""} > - + {link.url} @@ -264,7 +261,6 @@ export default function AddOrEditLink({ diff --git a/components/Modal/Link/PreservedFormats.tsx b/components/Modal/Link/PreservedFormats.tsx index f7b53455..a77941c2 100644 --- a/components/Modal/Link/PreservedFormats.tsx +++ b/components/Modal/Link/PreservedFormats.tsx @@ -4,12 +4,6 @@ import { } from "@/types/global"; import { useEffect, useState } from "react"; import Link from "next/link"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faArrowUpRightFromSquare, - faCloudArrowDown, -} from "@fortawesome/free-solid-svg-icons"; -import { faFileImage, faFilePdf } from "@fortawesome/free-regular-svg-icons"; import useLinkStore from "@/store/links"; import { toast } from "react-hot-toast"; import { useRouter } from "next/router"; @@ -97,7 +91,6 @@ export default function PreservedFormats() {
-

Screenshot

@@ -108,10 +101,6 @@ export default function PreservedFormats() { onClick={() => handleDownload(ArchivedFormat.png)} className="cursor-pointer hover:opacity-60 duration-100 p-2 rounded-md" > -
-
@@ -136,7 +121,6 @@ export default function PreservedFormats() {
-

PDF

@@ -147,10 +131,6 @@ export default function PreservedFormats() { onClick={() => handleDownload(ArchivedFormat.pdf)} className="cursor-pointer hover:opacity-60 duration-100 p-2 rounded-md" > -
-
@@ -191,10 +167,6 @@ export default function PreservedFormats() { screenshotAvailable(link) && pdfAvailable(link) ? "sm:mt-3" : "" }`} > -

View Latest Snapshot on archive.org

diff --git a/components/ModalContent/NewCollectionModal.tsx b/components/ModalContent/NewCollectionModal.tsx index de0fc98c..23b43444 100644 --- a/components/ModalContent/NewCollectionModal.tsx +++ b/components/ModalContent/NewCollectionModal.tsx @@ -1,11 +1,9 @@ import React, { useEffect, useState } from "react"; import TextInput from "@/components/TextInput"; import useCollectionStore from "@/store/collections"; -import toast, { Toaster } from "react-hot-toast"; -import { faFolder } from "@fortawesome/free-solid-svg-icons"; +import toast from "react-hot-toast"; import { HexColorPicker } from "react-colorful"; import { Collection } from "@prisma/client"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Modal from "../Modal"; type Props = { @@ -76,10 +74,6 @@ export default function NewCollectionModal({ onClose }: Props) {
-
- - + {/**/} + {/**/} {label} ); diff --git a/components/SubmitButton.tsx b/components/SubmitButton.tsx index 7a50b354..e86fa784 100644 --- a/components/SubmitButton.tsx +++ b/components/SubmitButton.tsx @@ -1,9 +1,5 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { IconProp } from "@fortawesome/fontawesome-svg-core"; - type Props = { onClick?: Function; - icon?: IconProp; label: string; loading: boolean; className?: string; @@ -12,7 +8,6 @@ type Props = { export default function SubmitButton({ onClick, - icon, label, loading, className, @@ -28,7 +23,6 @@ export default function SubmitButton({ if (!loading && onClick) onClick(); }} > - {icon && }

{label}

); diff --git a/layouts/LinkLayout.tsx b/layouts/LinkLayout.tsx deleted file mode 100644 index ddcced19..00000000 --- a/layouts/LinkLayout.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import LinkSidebar from "@/components/LinkSidebar"; -import { ReactNode, useEffect, useState } from "react"; -import ModalManagement from "@/components/ModalManagement"; -import useModalStore from "@/store/modals"; -import { useRouter } from "next/router"; -import ClickAwayHandler from "@/components/ClickAwayHandler"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faChevronLeft } from "@fortawesome/free-solid-svg-icons"; -import useWindowDimensions from "@/hooks/useWindowDimensions"; -import { - faPen, - faBoxesStacked, - faTrashCan, -} from "@fortawesome/free-solid-svg-icons"; -import useLinkStore from "@/store/links"; -import { - CollectionIncludingMembersAndLinkCount, - LinkIncludingShortenedCollectionAndTags, -} from "@/types/global"; -import { useSession } from "next-auth/react"; -import useCollectionStore from "@/store/collections"; -import EditLinkModal from "@/components/ModalContent/EditLinkModal"; -import Link from "next/link"; -import PreservedFormatsModal from "@/components/ModalContent/PreservedFormatsModal"; -import toast from "react-hot-toast"; -import DeleteLinkModal from "@/components/ModalContent/DeleteLinkModal"; - -interface Props { - children: ReactNode; -} - -export default function LinkLayout({ children }: Props) { - const { modal } = useModalStore(); - - const router = useRouter(); - - useEffect(() => { - modal - ? (document.body.style.overflow = "hidden") - : (document.body.style.overflow = "auto"); - }, [modal]); - - const [sidebar, setSidebar] = useState(false); - - const { width } = useWindowDimensions(); - - useEffect(() => { - setSidebar(false); - }, [width]); - - useEffect(() => { - setSidebar(false); - }, [router]); - - const toggleSidebar = () => { - setSidebar(!sidebar); - }; - - const session = useSession(); - const userId = session.data?.user.id; - - const { setModal } = useModalStore(); - - const { links, removeLink } = useLinkStore(); - const { collections } = useCollectionStore(); - - const [linkCollection, setLinkCollection] = - useState(); - - const [link, setLink] = useState(); - - useEffect(() => { - if (links[0]) setLink(links.find((e) => e.id === Number(router.query.id))); - }, [links]); - - useEffect(() => { - if (link) - setLinkCollection(collections.find((e) => e.id === link?.collection?.id)); - }, [link, collections]); - - const deleteLink = async () => { - const load = toast.loading("Deleting..."); - - const response = await removeLink(link?.id as number); - - toast.dismiss(load); - - response.ok && toast.success(`Link Deleted.`); - - router.push("/dashboard"); - }; - - const [editLinkModal, setEditLinkModal] = useState(false); - const [deleteLinkModal, setDeleteLinkModal] = useState(false); - const [preservedFormatsModal, setPreservedFormatsModal] = useState(false); - - return ( - <> -
- {/*
- -
*/} - -
-
- {/*
- -
*/} - - - - - {router.pathname.startsWith("/public") - ? linkCollection?.name || link?.collection?.name - : "Dashboard"} - - - -
- {link?.collection?.ownerId === userId || - linkCollection?.members.some( - (e) => e.userId === userId && e.canUpdate - ) ? ( -
setEditLinkModal(true)} - className={`btn btn-ghost btn-square btn-sm`} - > - -
- ) : undefined} - -
setPreservedFormatsModal(true)} - title="Preserved Formats" - className={`btn btn-ghost btn-square btn-sm`} - > - -
- - {link?.collection?.ownerId === userId || - linkCollection?.members.some( - (e) => e.userId === userId && e.canDelete - ) ? ( -
{ - (document?.activeElement as HTMLElement)?.blur(); - e.shiftKey ? deleteLink() : setDeleteLinkModal(true); - }} - title="Delete" - className={`btn btn-ghost btn-square btn-sm`} - > - -
- ) : undefined} -
-
- - {children} - - {sidebar ? ( -
- -
- setSidebar(false)} /> -
-
-
- ) : null} -
- {link && editLinkModal ? ( - setEditLinkModal(false)} - activeLink={link} - /> - ) : undefined} - {link && deleteLinkModal ? ( - setDeleteLinkModal(false)} - activeLink={link} - /> - ) : undefined} - {link && preservedFormatsModal ? ( - setPreservedFormatsModal(false)} - activeLink={link} - /> - ) : undefined} -
- - ); -} diff --git a/package.json b/package.json index 10cb9b34..27bf41aa 100644 --- a/package.json +++ b/package.json @@ -16,11 +16,6 @@ "dependencies": { "@auth/prisma-adapter": "^1.0.1", "@aws-sdk/client-s3": "^3.379.1", - "@fortawesome/fontawesome-svg-core": "^6.4.0", - "@fortawesome/free-brands-svg-icons": "^6.4.2", - "@fortawesome/free-regular-svg-icons": "^6.4.0", - "@fortawesome/free-solid-svg-icons": "^6.4.0", - "@fortawesome/react-fontawesome": "^0.2.0", "@headlessui/react": "^1.7.15", "@mozilla/readability": "^0.4.4", "@prisma/client": "^4.16.2", diff --git a/pages/api/v1/links/[id]/archive/index.ts b/pages/api/v1/links/[id]/archive/index.ts index fe8aaffa..065179fa 100644 --- a/pages/api/v1/links/[id]/archive/index.ts +++ b/pages/api/v1/links/[id]/archive/index.ts @@ -1,5 +1,5 @@ import type { NextApiRequest, NextApiResponse } from "next"; -import urlHandler from "@/lib/api/archiveHandler"; +import archiveHandler from "@/lib/api/archiveHandler"; import { prisma } from "@/lib/api/db"; import verifyUser from "@/lib/api/verifyUser"; import isValidUrl from "@/lib/shared/isValidUrl"; @@ -14,7 +14,7 @@ export default async function links(req: NextApiRequest, res: NextApiResponse) { where: { id: Number(req.query.id), }, - include: { collection: true }, + include: { collection: { include: { owner: true } } }, }); if (!link) @@ -43,7 +43,7 @@ export default async function links(req: NextApiRequest, res: NextApiResponse) { }); if (link.url && isValidUrl(link.url)) { - urlHandler(link.id, link.url, user.id); + archiveHandler(link); return res.status(200).json({ response: "Link is not a webpage to be archived.", }); diff --git a/yarn.lock b/yarn.lock index 705ecd0f..745672a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -781,51 +781,6 @@ dependencies: "@floating-ui/core" "^1.2.1" -"@fortawesome/fontawesome-common-types@6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz#88da2b70d6ca18aaa6ed3687832e11f39e80624b" - integrity sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ== - -"@fortawesome/fontawesome-common-types@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz#1766039cad33f8ad87f9467b98e0d18fbc8f01c5" - integrity sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA== - -"@fortawesome/fontawesome-svg-core@^6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz#3727552eff9179506e9203d72feb5b1063c11a21" - integrity sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw== - dependencies: - "@fortawesome/fontawesome-common-types" "6.4.0" - -"@fortawesome/free-brands-svg-icons@^6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.2.tgz#9b8e78066ea6dd563da5dfa686615791d0f7cc71" - integrity sha512-LKOwJX0I7+mR/cvvf6qIiqcERbdnY+24zgpUSouySml+5w8B4BJOx8EhDR/FTKAu06W12fmUIcv6lzPSwYKGGg== - dependencies: - "@fortawesome/fontawesome-common-types" "6.4.2" - -"@fortawesome/free-regular-svg-icons@^6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz#cacc53bd8d832d46feead412d9ea9ce80a55e13a" - integrity sha512-ZfycI7D0KWPZtf7wtMFnQxs8qjBXArRzczABuMQqecA/nXohquJ5J/RCR77PmY5qGWkxAZDxpnUFVXKwtY/jPw== - dependencies: - "@fortawesome/fontawesome-common-types" "6.4.0" - -"@fortawesome/free-solid-svg-icons@^6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz#48c0e790847fa56299e2f26b82b39663b8ad7119" - integrity sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ== - dependencies: - "@fortawesome/fontawesome-common-types" "6.4.0" - -"@fortawesome/react-fontawesome@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4" - integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw== - dependencies: - prop-types "^15.8.1" - "@headlessui/react@^1.7.15": version "1.7.15" resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.15.tgz#53ef6ae132af81b8f188414767b6e79ebf8dc73f"