From 9a3e82470a774766c1525c80fd3b7beaffbb77fd Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 18 Aug 2024 14:46:52 -0400 Subject: [PATCH] Revert "Feat/customizable links" --- components/CopyButton.tsx | 36 --- components/DashboardItem.tsx | 7 +- components/Drawer.tsx | 88 ----- components/IconPicker.tsx | 46 --- components/LinkDetails.tsx | 305 ------------------ .../LinkViews/LinkComponents/LinkActions.tsx | 223 ++++++------- .../LinkViews/LinkComponents/LinkCard.tsx | 62 +++- .../LinkViews/LinkComponents/LinkList.tsx | 20 +- .../LinkViews/LinkComponents/LinkMasonry.tsx | 57 +++- components/Modal.tsx | 2 +- .../EditCollectionSharingModal.tsx | 17 +- components/ModalContent/LinkDetailModal.tsx | 145 --------- components/ModalContent/NewLinkModal.tsx | 2 +- components/ModalContent/NewTokenModal.tsx | 24 +- .../ModalContent/PreservedFormatsModal.tsx | 6 +- components/ModalContent/UploadFileModal.tsx | 2 +- components/PreserverdFormatRow.tsx | 12 +- components/ReadableView.tsx | 21 +- hooks/store/links.tsx | 31 +- lib/client/icons.ts | 18 -- package.json | 9 +- pages/dashboard.tsx | 8 +- pages/links/[id].tsx | 41 --- pages/preserved/[id].tsx | 2 +- pages/public/links/[id].tsx | 41 --- pages/public/preserved/[id].tsx | 17 +- public/locales/en/common.json | 4 +- yarn.lock | 56 +--- 28 files changed, 326 insertions(+), 976 deletions(-) delete mode 100644 components/CopyButton.tsx delete mode 100644 components/Drawer.tsx delete mode 100644 components/IconPicker.tsx delete mode 100644 components/LinkDetails.tsx delete mode 100644 components/ModalContent/LinkDetailModal.tsx delete mode 100644 lib/client/icons.ts delete mode 100644 pages/links/[id].tsx delete mode 100644 pages/public/links/[id].tsx diff --git a/components/CopyButton.tsx b/components/CopyButton.tsx deleted file mode 100644 index 090d64b..0000000 --- a/components/CopyButton.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from "react"; - -type Props = { - text: string; -}; - -const CopyButton = ({ text }: Props) => { - return ( -
{ - try { - navigator.clipboard.writeText(text).then(() => { - const copyIcon = document.querySelector(".bi-copy"); - if (copyIcon) { - copyIcon.classList.remove("bi-copy"); - copyIcon.classList.add("bi-check2"); - copyIcon.classList.add("text-success"); - } - setTimeout(() => { - if (copyIcon) { - copyIcon.classList.remove("bi-check2"); - copyIcon.classList.remove("text-success"); - copyIcon.classList.add("bi-copy"); - } - }, 1000); - }); - } catch (err) { - console.log(err); - } - }} - >
- ); -}; - -export default CopyButton; diff --git a/components/DashboardItem.tsx b/components/DashboardItem.tsx index d255c4b..337fc36 100644 --- a/components/DashboardItem.tsx +++ b/components/DashboardItem.tsx @@ -14,12 +14,7 @@ export default function dashboardItem({

{name}

-

- {value < 1000 ? value : (value / 1000).toFixed(1) + "k"} -

-

- {value} -

+

{value}

); diff --git a/components/Drawer.tsx b/components/Drawer.tsx deleted file mode 100644 index 12f931e..0000000 --- a/components/Drawer.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, { ReactNode, useEffect } from "react"; -import ClickAwayHandler from "@/components/ClickAwayHandler"; -import { Drawer as D } from "vaul"; - -type Props = { - toggleDrawer: Function; - children: ReactNode; - className?: string; - dismissible?: boolean; -}; - -export default function Drawer({ - toggleDrawer, - className, - children, - dismissible = true, -}: Props) { - const [drawerIsOpen, setDrawerIsOpen] = React.useState(true); - - useEffect(() => { - if (window.innerWidth >= 640) { - document.body.style.overflow = "hidden"; - document.body.style.position = "relative"; - return () => { - document.body.style.overflow = "auto"; - document.body.style.position = ""; - }; - } - }, []); - - if (window.innerWidth < 640) { - return ( - dismissible && setTimeout(() => toggleDrawer(), 350)} - dismissible={dismissible} - > - - - dismissible && setDrawerIsOpen(false)} - > - -
-
- {children} -
- - - - - ); - } else { - return ( - dismissible && setTimeout(() => toggleDrawer(), 350)} - dismissible={dismissible} - direction="right" - > - - - dismissible && setDrawerIsOpen(false)} - className="z-30" - > - -
- {children} -
-
-
-
-
- ); - } -} diff --git a/components/IconPicker.tsx b/components/IconPicker.tsx deleted file mode 100644 index 994a5af..0000000 --- a/components/IconPicker.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { icons } from "@/lib/client/icons"; -import React, { useMemo, useState } from "react"; -import Fuse from "fuse.js"; -import TextInput from "./TextInput"; - -const fuse = new Fuse(icons, { - keys: [{ name: "name", weight: 4 }, "tags", "categories"], - threshold: 0.2, - useExtendedSearch: true, -}); - -type Props = {}; - -const IconPicker = (props: Props) => { - const [query, setQuery] = useState(""); - - const filteredQueryResultsSelector = useMemo(() => { - if (!query) { - return icons; - } - return fuse.search(query).map((result) => result.item); - }, [query]); - - return ( -
- setQuery(e.target.value)} - /> -
- {filteredQueryResultsSelector.map((icon) => { - const IconComponent = icon.Icon; - return ( -
console.log(icon.name)}> - -
- ); - })} -
-
- ); -}; - -export default IconPicker; diff --git a/components/LinkDetails.tsx b/components/LinkDetails.tsx deleted file mode 100644 index 0f237ca..0000000 --- a/components/LinkDetails.tsx +++ /dev/null @@ -1,305 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { - LinkIncludingShortenedCollectionAndTags, - ArchivedFormat, -} from "@/types/global"; -import Link from "next/link"; -import { useSession } from "next-auth/react"; -import { - pdfAvailable, - readabilityAvailable, - monolithAvailable, - screenshotAvailable, -} from "@/lib/shared/getArchiveValidity"; -import PreservedFormatRow from "@/components/PreserverdFormatRow"; -import getPublicUserData from "@/lib/client/getPublicUserData"; -import { useTranslation } from "next-i18next"; -import { BeatLoader } from "react-spinners"; -import { useUser } from "@/hooks/store/user"; -import { useGetLink } from "@/hooks/store/links"; -import LinkIcon from "./LinkViews/LinkComponents/LinkIcon"; -import CopyButton from "./CopyButton"; -import { useRouter } from "next/router"; - -type Props = { - className?: string; - link: LinkIncludingShortenedCollectionAndTags; -}; - -export default function LinkDetails({ className, link }: Props) { - const { t } = useTranslation(); - const session = useSession(); - const getLink = useGetLink(); - const { data: user = {} } = useUser(); - - const [collectionOwner, setCollectionOwner] = useState({ - id: null as unknown as number, - name: "", - username: "", - image: "", - archiveAsScreenshot: undefined as unknown as boolean, - archiveAsMonolith: undefined as unknown as boolean, - archiveAsPDF: undefined as unknown as boolean, - }); - - useEffect(() => { - const fetchOwner = async () => { - if (link.collection.ownerId !== user.id) { - const owner = await getPublicUserData( - link.collection.ownerId as number - ); - setCollectionOwner(owner); - } else if (link.collection.ownerId === user.id) { - setCollectionOwner({ - id: user.id as number, - name: user.name, - username: user.username as string, - image: user.image as string, - archiveAsScreenshot: user.archiveAsScreenshot as boolean, - archiveAsMonolith: user.archiveAsScreenshot as boolean, - archiveAsPDF: user.archiveAsPDF as boolean, - }); - } - }; - - fetchOwner(); - }, [link.collection.ownerId]); - - const isReady = () => { - return ( - link && - (collectionOwner.archiveAsScreenshot === true - ? link.pdf && link.pdf !== "pending" - : true) && - (collectionOwner.archiveAsMonolith === true - ? link.monolith && link.monolith !== "pending" - : true) && - (collectionOwner.archiveAsPDF === true - ? link.pdf && link.pdf !== "pending" - : true) && - link.readable && - link.readable !== "pending" - ); - }; - - const atLeastOneFormatAvailable = () => { - return ( - screenshotAvailable(link) || - pdfAvailable(link) || - readabilityAvailable(link) || - monolithAvailable(link) - ); - }; - - useEffect(() => { - (async () => { - await getLink.mutateAsync({ - id: link.id as number, - }); - })(); - - let interval: any; - - if (!isReady()) { - interval = setInterval(async () => { - await getLink.mutateAsync({ - id: link.id as number, - }); - }, 5000); - } else { - if (interval) { - clearInterval(interval); - } - } - - return () => { - if (interval) { - clearInterval(interval); - } - }; - }, [link?.monolith]); - - const router = useRouter(); - - const isPublicRoute = router.pathname.startsWith("/public") ? true : false; - - return ( -
- - - {link.name &&

{link.name}

} - - {link.url && ( - <> -
- -

{t("link")}

- -
-
- - {link.url} - -
- -
-
-
- - )} - -
- -

{t("collection")}

- -
- -

{link.collection.name}

-
- -
- -
- - {link.tags[0] && ( - <> -
- -
-

{t("tags")}

-
- -
- {link.tags.map((tag) => - isPublicRoute ? ( -
- {tag.name} -
- ) : ( - - {tag.name} - - ) - )} -
- - )} - - {link.description && ( - <> -
- -
-

{t("notes")}

- -
-

{link.description}

-
-
- - )} - -
- -

- {link.url ? t("preserved_formats") : t("file")} -

- -
- {monolithAvailable(link) ? ( - - ) : undefined} - - {screenshotAvailable(link) ? ( - - ) : undefined} - - {pdfAvailable(link) ? ( - - ) : undefined} - - {readabilityAvailable(link) ? ( - - ) : undefined} - - {!isReady() && !atLeastOneFormatAvailable() ? ( -
- - -

{t("preservation_in_queue")}

-

{t("check_back_later")}

-
- ) : link.url && !isReady() && atLeastOneFormatAvailable() ? ( -
- -

{t("there_are_more_formats")}

-

{t("check_back_later")}

-
- ) : undefined} - - {link.url && ( - -

{t("view_latest_snapshot")}

- - - )} -
-
- ); -} diff --git a/components/LinkViews/LinkComponents/LinkActions.tsx b/components/LinkViews/LinkComponents/LinkActions.tsx index 837cd6f..3abc06d 100644 --- a/components/LinkViews/LinkComponents/LinkActions.tsx +++ b/components/LinkViews/LinkComponents/LinkActions.tsx @@ -12,20 +12,22 @@ import { useTranslation } from "next-i18next"; import { useUser } from "@/hooks/store/user"; import { useDeleteLink, useUpdateLink } from "@/hooks/store/links"; import toast from "react-hot-toast"; -import LinkDetailModal from "@/components/ModalContent/LinkDetailModal"; -import { useRouter } from "next/router"; type Props = { link: LinkIncludingShortenedCollectionAndTags; collection: CollectionIncludingMembersAndLinkCount; position?: string; + toggleShowInfo?: () => void; + linkInfo?: boolean; alignToTop?: boolean; flipDropdown?: boolean; }; export default function LinkActions({ link, + toggleShowInfo, position, + linkInfo, alignToTop, flipDropdown, }: Props) { @@ -34,7 +36,6 @@ export default function LinkActions({ const permissions = usePermissions(link.collection.id as number); const [editLinkModal, setEditLinkModal] = useState(false); - const [linkDetailModal, setLinkDetailModal] = useState(false); const [deleteLinkModal, setDeleteLinkModal] = useState(false); const [preservedFormatsModal, setPreservedFormatsModal] = useState(false); @@ -69,137 +70,119 @@ export default function LinkActions({ ); }; - const router = useRouter(); - - const isPublicRoute = router.pathname.startsWith("/public") ? true : false; - return ( <> - {isPublicRoute ? ( +
setLinkDetailModal(true)} + tabIndex={0} + role="button" + onMouseDown={dropdownTriggerer} + className="btn btn-ghost btn-sm btn-square text-neutral" > -
- -
+
- ) : ( -
-
- -
-
    - {permissions === true || - (permissions?.canUpdate && ( -
  • -
    { - (document?.activeElement as HTMLElement)?.blur(); - pinLink(); - }} - className="whitespace-nowrap" - > - {link?.pinnedBy && link.pinnedBy[0] - ? t("unpin") - : t("pin_to_dashboard")} -
    -
  • - ))} +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + pinLink(); + }} + className="whitespace-nowrap" + > + {link?.pinnedBy && link.pinnedBy[0] + ? t("unpin") + : t("pin_to_dashboard")} +
    +
  • + {linkInfo !== undefined && toggleShowInfo ? (
  • { (document?.activeElement as HTMLElement)?.blur(); - setLinkDetailModal(true); + toggleShowInfo(); }} className="whitespace-nowrap" > - {t("show_link_details")} + {!linkInfo ? t("show_link_details") : t("hide_link_details")}
  • - {permissions === true || permissions?.canUpdate ? ( -
  • -
    { - (document?.activeElement as HTMLElement)?.blur(); - setEditLinkModal(true); - }} - className="whitespace-nowrap" - > - {t("edit_link")} -
    -
  • - ) : undefined} - {link.type === "url" && ( -
  • -
    { - (document?.activeElement as HTMLElement)?.blur(); - setPreservedFormatsModal(true); - }} - className="whitespace-nowrap" - > - {t("preserved_formats")} -
    -
  • - )} - {permissions === true || permissions?.canDelete ? ( -
  • -
    { - (document?.activeElement as HTMLElement)?.blur(); - e.shiftKey - ? async () => { - const load = toast.loading(t("deleting")); + ) : undefined} + {permissions === true || permissions?.canUpdate ? ( +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setEditLinkModal(true); + }} + className="whitespace-nowrap" + > + {t("edit_link")} +
    +
  • + ) : undefined} + {link.type === "url" && ( +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setPreservedFormatsModal(true); + }} + className="whitespace-nowrap" + > + {t("preserved_formats")} +
    +
  • + )} + {permissions === true || permissions?.canDelete ? ( +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + e.shiftKey + ? async () => { + const load = toast.loading(t("deleting")); - await deleteLink.mutateAsync(link.id as number, { - onSettled: (data, error) => { - toast.dismiss(load); + await deleteLink.mutateAsync(link.id as number, { + onSettled: (data, error) => { + toast.dismiss(load); - if (error) { - toast.error(error.message); - } else { - toast.success(t("deleted")); - } - }, - }); - } - : setDeleteLinkModal(true); - }} - className="whitespace-nowrap" - > - {t("delete")} -
    -
  • - ) : undefined} -
-
- )} + if (error) { + toast.error(error.message); + } else { + toast.success(t("deleted")); + } + }, + }); + } + : setDeleteLinkModal(true); + }} + className="whitespace-nowrap" + > + {t("delete")} +
+ + ) : undefined} + +
{editLinkModal ? ( ) : undefined} - {linkDetailModal ? ( - setLinkDetailModal(false)} - onEdit={() => setEditLinkModal(true)} - link={link} - /> - ) : undefined} + {/* {expandedLink ? ( + setExpandedLink(false)} link={link} /> + ) : undefined} */} ); } diff --git a/components/LinkViews/LinkComponents/LinkCard.tsx b/components/LinkViews/LinkComponents/LinkCard.tsx index c6b60c5..e228fb1 100644 --- a/components/LinkViews/LinkComponents/LinkCard.tsx +++ b/components/LinkViews/LinkComponents/LinkCard.tsx @@ -22,7 +22,6 @@ import { useTranslation } from "next-i18next"; import { useCollections } from "@/hooks/store/collections"; import { useUser } from "@/hooks/store/user"; import { useGetLink, useLinks } from "@/hooks/store/links"; -import { useRouter } from "next/router"; type Props = { link: LinkIncludingShortenedCollectionAndTags; @@ -91,10 +90,6 @@ export default function LinkCard({ link, flipDropdown, editMode }: Props) { const isVisible = useOnScreen(ref); const permissions = usePermissions(collection?.id as number); - const router = useRouter(); - - let isPublic = router.pathname.startsWith("/public") ? true : undefined; - useEffect(() => { let interval: any; @@ -104,7 +99,7 @@ export default function LinkCard({ link, flipDropdown, editMode }: Props) { link.preview !== "unavailable" ) { interval = setInterval(async () => { - getLink.mutateAsync({ id: link.id as number, isPublicRoute: isPublic }); + getLink.mutateAsync(link.id as number); }, 5000); } @@ -115,6 +110,8 @@ export default function LinkCard({ link, flipDropdown, editMode }: Props) { }; }, [isVisible, link.preview]); + const [showInfo, setShowInfo] = useState(false); + const selectedStyle = selectedLinks.some( (selectedLink) => selectedLink.id === link.id ) @@ -199,10 +196,63 @@ export default function LinkCard({ link, flipDropdown, editMode }: Props) { + {showInfo && ( +
+
setShowInfo(!showInfo)} + className=" float-right btn btn-sm outline-none btn-circle btn-ghost z-10" + > + +
+

+ {t("description")} +

+ +
+

+ {link.description ? ( + unescapeString(link.description) + ) : ( + + {t("no_description")} + + )} +

+ {link.tags && link.tags[0] && ( + <> +

+ {t("tags")} +

+ +
+ +
+
+ {link.tags.map((e, i) => ( + { + e.stopPropagation(); + }} + className="btn btn-xs btn-ghost truncate max-w-[19rem]" + > + #{e.name} + + ))} +
+
+ + )} +
+ )} + setShowInfo(!showInfo)} + linkInfo={showInfo} flipDropdown={flipDropdown} /> diff --git a/components/LinkViews/LinkComponents/LinkList.tsx b/components/LinkViews/LinkComponents/LinkList.tsx index 59e6e2d..d3c8d40 100644 --- a/components/LinkViews/LinkComponents/LinkList.tsx +++ b/components/LinkViews/LinkComponents/LinkList.tsx @@ -80,6 +80,8 @@ export default function LinkCardCompact({ const permissions = usePermissions(collection?.id as number); + const [showInfo, setShowInfo] = useState(false); + const selectedStyle = selectedLinks.some( (selectedLink) => selectedLink.id === link.id ) @@ -94,7 +96,7 @@ export default function LinkCardCompact({ <>
selectable @@ -104,6 +106,20 @@ export default function LinkCardCompact({ : undefined } > + {/* {showCheckbox && + editMode && + (permissions === true || + permissions?.canCreate || + permissions?.canDelete) && ( + selectedLink.id === link.id + )} + onChange={() => handleCheckboxClick(link)} + /> + )} */}
@@ -141,6 +157,8 @@ export default function LinkCardCompact({ collection={collection} position="top-3 right-3" flipDropdown={flipDropdown} + // toggleShowInfo={() => setShowInfo(!showInfo)} + // linkInfo={showInfo} />
{ - getLink.mutateAsync({ id: link.id as number }); + getLink.mutateAsync(link.id as number); }, 5000); } @@ -107,6 +107,8 @@ export default function LinkMasonry({ link, flipDropdown, editMode }: Props) { }; }, [isVisible, link.preview]); + const [showInfo, setShowInfo] = useState(false); + const selectedStyle = selectedLinks.some( (selectedLink) => selectedLink.id === link.id ) @@ -205,6 +207,57 @@ export default function LinkMasonry({ link, flipDropdown, editMode }: Props) {
+ {showInfo && ( +
+
setShowInfo(!showInfo)} + className=" float-right btn btn-sm outline-none btn-circle btn-ghost z-10" + > + +
+

+ {t("description")} +

+ +
+

+ {link.description ? ( + unescapeString(link.description) + ) : ( + + {t("no_description")} + + )} +

+ {link.tags && link.tags[0] && ( + <> +

+ {t("tags")} +

+ +
+ +
+
+ {link.tags.map((e, i) => ( + { + e.stopPropagation(); + }} + className="btn btn-xs btn-ghost truncate max-w-[19rem]" + > + #{e.name} + + ))} +
+
+ + )} +
+ )} + setShowInfo(!showInfo)} + linkInfo={showInfo} flipDropdown={flipDropdown} /> diff --git a/components/Modal.tsx b/components/Modal.tsx index 2eb97e4..4691df7 100644 --- a/components/Modal.tsx +++ b/components/Modal.tsx @@ -32,7 +32,7 @@ export default function Modal({ return ( dismissible && setTimeout(() => toggleModal(), 350)} + onClose={() => dismissible && setTimeout(() => toggleModal(), 100)} dismissible={dismissible} > diff --git a/components/ModalContent/EditCollectionSharingModal.tsx b/components/ModalContent/EditCollectionSharingModal.tsx index 321e672..f004af4 100644 --- a/components/ModalContent/EditCollectionSharingModal.tsx +++ b/components/ModalContent/EditCollectionSharingModal.tsx @@ -11,7 +11,6 @@ import { dropdownTriggerer } from "@/lib/client/utils"; import { useTranslation } from "next-i18next"; import { useUpdateCollection } from "@/hooks/store/collections"; import { useUser } from "@/hooks/store/user"; -import CopyButton from "../CopyButton"; type Props = { onClose: Function; @@ -134,11 +133,21 @@ export default function EditCollectionSharingModal({ )} {collection.isPublic ? ( -
+

{t("sharable_link_guide")}

-
+
{ + try { + navigator.clipboard + .writeText(publicCollectionURL) + .then(() => toast.success(t("copied"))); + } catch (err) { + console.log(err); + } + }} + className="w-full hide-scrollbar overflow-x-auto whitespace-nowrap rounded-md p-2 bg-base-200 border-neutral-content border-solid border outline-none hover:border-primary dark:hover:border-primary duration-100 cursor-text" + > {publicCollectionURL} -
) : null} diff --git a/components/ModalContent/LinkDetailModal.tsx b/components/ModalContent/LinkDetailModal.tsx deleted file mode 100644 index e9f0086..0000000 --- a/components/ModalContent/LinkDetailModal.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; -import getPublicUserData from "@/lib/client/getPublicUserData"; -import { useTranslation } from "next-i18next"; -import { useUser } from "@/hooks/store/user"; -import { useGetLink } from "@/hooks/store/links"; -import Drawer from "../Drawer"; -import LinkDetails from "../LinkDetails"; -import Link from "next/link"; -import usePermissions from "@/hooks/usePermissions"; -import { useRouter } from "next/router"; - -type Props = { - onClose: Function; - onEdit: Function; - link: LinkIncludingShortenedCollectionAndTags; -}; - -export default function LinkDetailModal({ onClose, onEdit, link }: Props) { - const { t } = useTranslation(); - const getLink = useGetLink(); - const { data: user = {} } = useUser(); - - const [collectionOwner, setCollectionOwner] = useState({ - id: null as unknown as number, - name: "", - username: "", - image: "", - archiveAsScreenshot: undefined as unknown as boolean, - archiveAsMonolith: undefined as unknown as boolean, - archiveAsPDF: undefined as unknown as boolean, - }); - - useEffect(() => { - const fetchOwner = async () => { - if (link.collection.ownerId !== user.id) { - const owner = await getPublicUserData( - link.collection.ownerId as number - ); - setCollectionOwner(owner); - } else if (link.collection.ownerId === user.id) { - setCollectionOwner({ - id: user.id as number, - name: user.name, - username: user.username as string, - image: user.image as string, - archiveAsScreenshot: user.archiveAsScreenshot as boolean, - archiveAsMonolith: user.archiveAsScreenshot as boolean, - archiveAsPDF: user.archiveAsPDF as boolean, - }); - } - }; - - fetchOwner(); - }, [link.collection.ownerId]); - - const isReady = () => { - return ( - link && - (collectionOwner.archiveAsScreenshot === true - ? link.pdf && link.pdf !== "pending" - : true) && - (collectionOwner.archiveAsMonolith === true - ? link.monolith && link.monolith !== "pending" - : true) && - (collectionOwner.archiveAsPDF === true - ? link.pdf && link.pdf !== "pending" - : true) && - link.readable && - link.readable !== "pending" - ); - }; - - useEffect(() => { - (async () => { - await getLink.mutateAsync({ - id: link.id as number, - }); - })(); - - let interval: any; - - if (!isReady()) { - interval = setInterval(async () => { - await getLink.mutateAsync({ - id: link.id as number, - }); - }, 5000); - } else { - if (interval) { - clearInterval(interval); - } - } - - return () => { - if (interval) { - clearInterval(interval); - } - }; - }, [link?.monolith]); - - const permissions = usePermissions(link.collection.id as number); - - const router = useRouter(); - - const isPublicRoute = router.pathname.startsWith("/public") ? true : false; - - return ( - -
onClose()} - >
- - -
- - - {permissions === true || - (permissions?.canUpdate && ( - <> -
-
- -
-
{ - onEdit(); - onClose(); - }} - > - {t("edit_link")} -
-
- - ))} -
-
- ); -} diff --git a/components/ModalContent/NewLinkModal.tsx b/components/ModalContent/NewLinkModal.tsx index ff628bf..660c1e4 100644 --- a/components/ModalContent/NewLinkModal.tsx +++ b/components/ModalContent/NewLinkModal.tsx @@ -61,7 +61,7 @@ export default function NewLinkModal({ onClose }: Props) { }; useEffect(() => { - if (router.pathname.startsWith("/collections/") && router.query.id) { + if (router.query.id) { const currentCollection = collections.find( (e) => e.id == Number(router.query.id) ); diff --git a/components/ModalContent/NewTokenModal.tsx b/components/ModalContent/NewTokenModal.tsx index 5c57012..4d39aec 100644 --- a/components/ModalContent/NewTokenModal.tsx +++ b/components/ModalContent/NewTokenModal.tsx @@ -7,7 +7,6 @@ import { dropdownTriggerer } from "@/lib/client/utils"; import Button from "../ui/Button"; import { useTranslation } from "next-i18next"; import { useAddToken } from "@/hooks/store/tokens"; -import CopyButton from "../CopyButton"; type Props = { onClose: Function; @@ -69,14 +68,21 @@ export default function NewTokenModal({ onClose }: Props) {

{t("access_token_created")}

{t("token_creation_notice")}

-
-
- {newToken} -
- -
-
-
+ {}} + className="w-full" + /> +
) : ( <> diff --git a/components/ModalContent/PreservedFormatsModal.tsx b/components/ModalContent/PreservedFormatsModal.tsx index 309170a..7cd1df0 100644 --- a/components/ModalContent/PreservedFormatsModal.tsx +++ b/components/ModalContent/PreservedFormatsModal.tsx @@ -96,14 +96,14 @@ export default function PreservedFormatsModal({ onClose, link }: Props) { useEffect(() => { (async () => { - await getLink.mutateAsync({ id: link.id as number }); + await getLink.mutateAsync(link.id as number); })(); let interval: any; if (!isReady()) { interval = setInterval(async () => { - await getLink.mutateAsync({ id: link.id as number }); + await getLink.mutateAsync(link.id as number); }, 5000); } else { if (interval) { @@ -129,7 +129,7 @@ export default function PreservedFormatsModal({ onClose, link }: Props) { toast.dismiss(load); if (response.ok) { - await getLink.mutateAsync({ id: link.id as number }); + await getLink.mutateAsync(link?.id as number); toast.success(t("link_being_archived")); } else toast.error(data.response); diff --git a/components/ModalContent/UploadFileModal.tsx b/components/ModalContent/UploadFileModal.tsx index 85ecaff..bbb1577 100644 --- a/components/ModalContent/UploadFileModal.tsx +++ b/components/ModalContent/UploadFileModal.tsx @@ -70,7 +70,7 @@ export default function UploadFileModal({ onClose }: Props) { useEffect(() => { setOptionsExpanded(false); - if (router.pathname.startsWith("/collections/") && router.query.id) { + if (router.query.id) { const currentCollection = collections.find( (e) => e.id == Number(router.query.id) ); diff --git a/components/PreserverdFormatRow.tsx b/components/PreserverdFormatRow.tsx index 45b156f..e8ddbd1 100644 --- a/components/PreserverdFormatRow.tsx +++ b/components/PreserverdFormatRow.tsx @@ -52,9 +52,11 @@ export default function PreservedFormatRow({ }; return ( -
+
- +
+ +

{name}

@@ -62,7 +64,7 @@ export default function PreservedFormatRow({ {downloadable || false ? (
handleDownload()} - className="btn btn-sm btn-square btn-ghost" + className="btn btn-sm btn-square" >
@@ -73,9 +75,9 @@ export default function PreservedFormatRow({ isPublic ? "/public" : "" }/preserved/${link?.id}?format=${format}`} target="_blank" - className="btn btn-sm btn-square btn-ghost" + className="btn btn-sm btn-square" > - +
diff --git a/components/ReadableView.tsx b/components/ReadableView.tsx index def3185..801e9c1 100644 --- a/components/ReadableView.tsx +++ b/components/ReadableView.tsx @@ -46,6 +46,13 @@ export default function ReadableView({ link }: Props) { const router = useRouter(); const getLink = useGetLink(); + const { data: collections = [] } = useCollections(); + + const collection = useMemo(() => { + return collections.find( + (e) => e.id === link.collection.id + ) as CollectionIncludingMembersAndLinkCount; + }, [collections, link]); useEffect(() => { const fetchLinkContent = async () => { @@ -66,7 +73,7 @@ export default function ReadableView({ link }: Props) { }, [link]); useEffect(() => { - if (link) getLink.mutateAsync({ id: link.id as number }); + if (link) getLink.mutateAsync(link?.id as number); let interval: any; if ( @@ -81,10 +88,7 @@ export default function ReadableView({ link }: Props) { !link?.monolith) ) { interval = setInterval( - () => - getLink.mutateAsync({ - id: link.id as number, - }), + () => getLink.mutateAsync(link.id as number), 5000 ); } else { @@ -239,6 +243,13 @@ export default function ReadableView({ link }: Props) { {link?.name ?

{unescapeString(link?.description)}

: undefined}
+ +
diff --git a/hooks/store/links.tsx b/hooks/store/links.tsx index 6d2177f..abd5624 100644 --- a/hooks/store/links.tsx +++ b/hooks/store/links.tsx @@ -225,21 +225,9 @@ const useDeleteLink = () => { const useGetLink = () => { const queryClient = useQueryClient(); - const router = useRouter(); - return useMutation({ - mutationFn: async ({ - id, - isPublicRoute = router.pathname.startsWith("/public") ? true : undefined, - }: { - id: number; - isPublicRoute?: boolean; - }) => { - const path = isPublicRoute - ? `/api/v1/public/links/${id}` - : `/api/v1/links/${id}`; - - const response = await fetch(path); + mutationFn: async (id: number) => { + const response = await fetch(`/api/v1/links/${id}`); const data = await response.json(); if (!response.ok) throw new Error(data.response); @@ -262,20 +250,7 @@ const useGetLink = () => { }; }); - queryClient.setQueriesData( - { queryKey: ["publicLinks"] }, - (oldData: any) => { - if (!oldData) return undefined; - return { - pages: oldData.pages.map((page: any) => - page.map((item: any) => (item.id === data.id ? data : item)) - ), - pageParams: oldData.pageParams, - }; - } - ); - - // queryClient.invalidateQueries({ queryKey: ["publicLinks"] }); + queryClient.invalidateQueries({ queryKey: ["publicLinks"] }); }, }); }; diff --git a/lib/client/icons.ts b/lib/client/icons.ts deleted file mode 100644 index 2083bd0..0000000 --- a/lib/client/icons.ts +++ /dev/null @@ -1,18 +0,0 @@ -import * as Icons from "@phosphor-icons/react"; -import { icons as iconData } from "@phosphor-icons/core"; -import { IconEntry as CoreEntry } from "@phosphor-icons/core"; - -interface IconEntry extends CoreEntry { - Icon: Icons.Icon; -} - -export const icons: ReadonlyArray = iconData.map((entry) => ({ - ...entry, - Icon: Icons[entry.pascal_name as keyof typeof Icons] as Icons.Icon, -})); - -if (process.env.NODE_ENV === "development") { - console.log(`${icons.length} icons`); -} - -export const iconCount = Intl.NumberFormat("en-US").format(icons.length * 6); diff --git a/package.json b/package.json index 0e72474..0850217 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "linkwarden", - "version": "v2.8.0", + "version": "v2.7.1", "main": "index.js", "repository": "https://github.com/linkwarden/linkwarden.git", "author": "Daniel31X13 ", @@ -25,8 +25,6 @@ "@aws-sdk/client-s3": "^3.379.1", "@headlessui/react": "^1.7.15", "@mozilla/readability": "^0.4.4", - "@phosphor-icons/core": "^2.1.1", - "@phosphor-icons/react": "^2.1.7", "@prisma/client": "^4.16.2", "@stripe/stripe-js": "^1.54.1", "@tanstack/react-query": "^5.51.15", @@ -52,7 +50,6 @@ "eslint-config-next": "13.4.9", "formidable": "^3.5.1", "framer-motion": "^10.16.4", - "fuse.js": "^7.0.0", "handlebars": "^4.7.8", "himalaya": "^1.1.0", "i18next": "^23.11.5", @@ -79,7 +76,7 @@ "socks-proxy-agent": "^8.0.2", "stripe": "^12.13.0", "tailwind-merge": "^2.3.0", - "vaul": "^0.9.1", + "vaul": "^0.8.8", "zustand": "^4.3.8" }, "devDependencies": { @@ -95,7 +92,7 @@ "postcss": "^8.4.26", "prettier": "3.1.1", "prisma": "^4.16.2", - "tailwindcss": "^3.4.10", + "tailwindcss": "^3.3.3", "ts-node": "^10.9.2", "typescript": "4.9.4" } diff --git a/pages/dashboard.tsx b/pages/dashboard.tsx index 7f59a3b..5ee0f2d 100644 --- a/pages/dashboard.tsx +++ b/pages/dashboard.tsx @@ -111,14 +111,14 @@ export default function Dashboard() {
-
+
-
+
-
+
diff --git a/pages/links/[id].tsx b/pages/links/[id].tsx deleted file mode 100644 index 9f2aaec..0000000 --- a/pages/links/[id].tsx +++ /dev/null @@ -1,41 +0,0 @@ -import LinkDetails from "@/components/LinkDetails"; -import { useGetLink } from "@/hooks/store/links"; -import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; -import getServerSideProps from "@/lib/client/getServerSideProps"; - -const Index = () => { - const router = useRouter(); - const { id } = router.query; - - useState; - - const getLink = useGetLink(); - - useEffect(() => { - getLink.mutate({ id: Number(id) }); - }, []); - - return ( -
- {getLink.data ? ( - - ) : ( -
-
-
-
-
-
-
- )} -
- ); -}; - -export default Index; - -export { getServerSideProps }; diff --git a/pages/preserved/[id].tsx b/pages/preserved/[id].tsx index de21605..c5806ff 100644 --- a/pages/preserved/[id].tsx +++ b/pages/preserved/[id].tsx @@ -20,7 +20,7 @@ export default function Index() { useEffect(() => { const fetchLink = async () => { if (router.query.id) { - await getLink.mutateAsync({ id: Number(router.query.id) }); + await getLink.mutateAsync(Number(router.query.id)); } }; diff --git a/pages/public/links/[id].tsx b/pages/public/links/[id].tsx deleted file mode 100644 index 9f2aaec..0000000 --- a/pages/public/links/[id].tsx +++ /dev/null @@ -1,41 +0,0 @@ -import LinkDetails from "@/components/LinkDetails"; -import { useGetLink } from "@/hooks/store/links"; -import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; -import getServerSideProps from "@/lib/client/getServerSideProps"; - -const Index = () => { - const router = useRouter(); - const { id } = router.query; - - useState; - - const getLink = useGetLink(); - - useEffect(() => { - getLink.mutate({ id: Number(id) }); - }, []); - - return ( -
- {getLink.data ? ( - - ) : ( -
-
-
-
-
-
-
- )} -
- ); -}; - -export default Index; - -export { getServerSideProps }; diff --git a/pages/public/preserved/[id].tsx b/pages/public/preserved/[id].tsx index 31544b0..2f415ae 100644 --- a/pages/public/preserved/[id].tsx +++ b/pages/public/preserved/[id].tsx @@ -6,9 +6,10 @@ import { } from "@/types/global"; import ReadableView from "@/components/ReadableView"; import getServerSideProps from "@/lib/client/getServerSideProps"; -import { useGetLink } from "@/hooks/store/links"; +import { useGetLink, useLinks } from "@/hooks/store/links"; export default function Index() { + const { links } = useLinks(); const getLink = useGetLink(); const [link, setLink] = useState(); @@ -18,14 +19,18 @@ export default function Index() { useEffect(() => { const fetchLink = async () => { if (router.query.id) { - const get = await getLink.mutateAsync({ id: Number(router.query.id) }); - setLink(get); + await getLink.mutateAsync(Number(router.query.id)); } }; fetchLink(); }, []); + useEffect(() => { + if (links && links[0]) + setLink(links.find((e) => e.id === Number(router.query.id))); + }, [links]); + return (
{/*
@@ -34,12 +39,6 @@ export default function Index() { {link && Number(router.query.format) === ArchivedFormat.readability && ( )} - {link && Number(router.query.format) === ArchivedFormat.monolith && ( - - )} {link && Number(router.query.format) === ArchivedFormat.pdf && (