diff --git a/components/LinkViews/Layouts/CardView.tsx b/components/LinkViews/Layouts/CardView.tsx deleted file mode 100644 index 8e85431..0000000 --- a/components/LinkViews/Layouts/CardView.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import LinkCard from "@/components/LinkViews/LinkCard"; -import { useLinks } from "@/hooks/store/links"; -import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; -import { useEffect } from "react"; -import { useInView } from "react-intersection-observer"; -import { GridLoader } from "react-spinners"; - -export default function CardView({ - links, - editMode, - isLoading, -}: { - links: LinkIncludingShortenedCollectionAndTags[]; - editMode?: boolean; - isLoading?: boolean; -}) { - const { ref, inView } = useInView(); - - const { data } = useLinks(); - - useEffect(() => { - if (inView) { - data.fetchNextPage(); - } - }, [data.fetchNextPage, inView]); - - return ( -
- {links.map((e, i) => { - return ( - - ); - })} - - {data.hasNextPage && ( -
-
-
-
-
-
- )} - - {isLoading && links.length > 0 && ( - - )} -
- ); -} diff --git a/components/LinkViews/Layouts/ListView.tsx b/components/LinkViews/Layouts/ListView.tsx deleted file mode 100644 index a83609c..0000000 --- a/components/LinkViews/Layouts/ListView.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import LinkList from "@/components/LinkViews/LinkList"; -import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; -import { GridLoader } from "react-spinners"; - -export default function ListView({ - links, - editMode, - isLoading, -}: { - links: LinkIncludingShortenedCollectionAndTags[]; - editMode?: boolean; - isLoading?: boolean; -}) { - return ( -
- {links.map((e, i) => { - return ( - - ); - })} - - {isLoading && links.length > 0 && ( - - )} -
- ); -} diff --git a/components/LinkViews/Layouts/MasonryView.tsx b/components/LinkViews/Layouts/MasonryView.tsx deleted file mode 100644 index bceaf33..0000000 --- a/components/LinkViews/Layouts/MasonryView.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import LinkMasonry from "@/components/LinkViews/LinkMasonry"; -import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; -import { GridLoader } from "react-spinners"; -import Masonry from "react-masonry-css"; -import resolveConfig from "tailwindcss/resolveConfig"; -import tailwindConfig from "../../../tailwind.config.js"; -import { useMemo } from "react"; - -export default function MasonryView({ - links, - editMode, - isLoading, -}: { - links: LinkIncludingShortenedCollectionAndTags[]; - editMode?: boolean; - isLoading?: boolean; -}) { - const fullConfig = resolveConfig(tailwindConfig as any); - - const breakpointColumnsObj = useMemo(() => { - return { - default: 5, - 1900: 4, - 1500: 3, - 880: 2, - 550: 1, - }; - }, []); - - return ( - - {links.map((e, i) => { - return ( - - ); - })} - - {isLoading && links.length > 0 && ( - - )} - - ); -} diff --git a/components/LinkViews/LinkComponents/LinkActions.tsx b/components/LinkViews/LinkComponents/LinkActions.tsx index ffa0051..6d55d85 100644 --- a/components/LinkViews/LinkComponents/LinkActions.tsx +++ b/components/LinkViews/LinkComponents/LinkActions.tsx @@ -162,7 +162,7 @@ export default function LinkActions({ {preservedFormatsModal ? ( setPreservedFormatsModal(false)} - activeLink={link} + link={link} /> ) : undefined} {/* {expandedLink ? ( diff --git a/components/LinkViews/LinkCard.tsx b/components/LinkViews/LinkComponents/LinkCard.tsx similarity index 98% rename from components/LinkViews/LinkCard.tsx rename to components/LinkViews/LinkComponents/LinkCard.tsx index b6e764b..e228fb1 100644 --- a/components/LinkViews/LinkCard.tsx +++ b/components/LinkViews/LinkComponents/LinkCard.tsx @@ -12,12 +12,12 @@ import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection import Image from "next/image"; import { previewAvailable } from "@/lib/shared/getArchiveValidity"; import Link from "next/link"; -import LinkIcon from "./LinkComponents/LinkIcon"; +import LinkIcon from "./LinkIcon"; import useOnScreen from "@/hooks/useOnScreen"; import { generateLinkHref } from "@/lib/client/generateLinkHref"; import usePermissions from "@/hooks/usePermissions"; import toast from "react-hot-toast"; -import LinkTypeBadge from "./LinkComponents/LinkTypeBadge"; +import LinkTypeBadge from "./LinkTypeBadge"; import { useTranslation } from "next-i18next"; import { useCollections } from "@/hooks/store/collections"; import { useUser } from "@/hooks/store/user"; diff --git a/components/LinkViews/LinkList.tsx b/components/LinkViews/LinkComponents/LinkList.tsx similarity index 98% rename from components/LinkViews/LinkList.tsx rename to components/LinkViews/LinkComponents/LinkList.tsx index ac17c68..d3c8d40 100644 --- a/components/LinkViews/LinkList.tsx +++ b/components/LinkViews/LinkComponents/LinkList.tsx @@ -13,7 +13,7 @@ import { isPWA } from "@/lib/client/utils"; import { generateLinkHref } from "@/lib/client/generateLinkHref"; import usePermissions from "@/hooks/usePermissions"; import toast from "react-hot-toast"; -import LinkTypeBadge from "./LinkComponents/LinkTypeBadge"; +import LinkTypeBadge from "./LinkTypeBadge"; import { useTranslation } from "next-i18next"; import { useCollections } from "@/hooks/store/collections"; import { useUser } from "@/hooks/store/user"; diff --git a/components/LinkViews/LinkMasonry.tsx b/components/LinkViews/LinkComponents/LinkMasonry.tsx similarity index 98% rename from components/LinkViews/LinkMasonry.tsx rename to components/LinkViews/LinkComponents/LinkMasonry.tsx index 0c20395..3d327a1 100644 --- a/components/LinkViews/LinkMasonry.tsx +++ b/components/LinkViews/LinkComponents/LinkMasonry.tsx @@ -12,12 +12,12 @@ import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection import Image from "next/image"; import { previewAvailable } from "@/lib/shared/getArchiveValidity"; import Link from "next/link"; -import LinkIcon from "./LinkComponents/LinkIcon"; +import LinkIcon from "./LinkIcon"; import useOnScreen from "@/hooks/useOnScreen"; import { generateLinkHref } from "@/lib/client/generateLinkHref"; import usePermissions from "@/hooks/usePermissions"; import toast from "react-hot-toast"; -import LinkTypeBadge from "./LinkComponents/LinkTypeBadge"; +import LinkTypeBadge from "./LinkTypeBadge"; import { useTranslation } from "next-i18next"; import { useCollections } from "@/hooks/store/collections"; import { useUser } from "@/hooks/store/user"; diff --git a/components/LinkViews/Links.tsx b/components/LinkViews/Links.tsx index a90cf77..11720dc 100644 --- a/components/LinkViews/Links.tsx +++ b/components/LinkViews/Links.tsx @@ -1,18 +1,16 @@ -import LinkCard from "@/components/LinkViews/LinkCard"; -import { useLinks } from "@/hooks/store/links"; +import LinkCard from "@/components/LinkViews/LinkComponents/LinkCard"; import { LinkIncludingShortenedCollectionAndTags, ViewMode, } from "@/types/global"; -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { useInView } from "react-intersection-observer"; -import { GridLoader } from "react-spinners"; -import LinkMasonry from "@/components/LinkViews/LinkMasonry"; +import LinkMasonry from "@/components/LinkViews/LinkComponents/LinkMasonry"; import Masonry from "react-masonry-css"; import resolveConfig from "tailwindcss/resolveConfig"; import tailwindConfig from "../../tailwind.config.js"; import { useMemo } from "react"; -import LinkList from "@/components/LinkViews/LinkList"; +import LinkList from "@/components/LinkViews/LinkComponents/LinkList"; export function CardView({ links, @@ -59,15 +57,6 @@ export function CardView({ ); })} - - {/* {isLoading && links.length > 0 && ( - - )} */} ); } @@ -100,15 +89,6 @@ export function ListView({ /> ); })} - - {/* {isLoading && links.length > 0 && ( - - )} */} ); } @@ -157,15 +137,6 @@ export function MasonryView({ /> ); })} - - {/* {isLoading && links.length > 0 && ( - - )} */} ); } diff --git a/components/ModalContent/BulkEditLinksModal.tsx b/components/ModalContent/BulkEditLinksModal.tsx index 5f3d31a..3797e38 100644 --- a/components/ModalContent/BulkEditLinksModal.tsx +++ b/components/ModalContent/BulkEditLinksModal.tsx @@ -6,6 +6,7 @@ import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; import toast from "react-hot-toast"; import Modal from "../Modal"; import { useTranslation } from "next-i18next"; +import { useBulkEditLinks } from "@/hooks/store/links"; type Props = { onClose: Function; @@ -13,13 +14,14 @@ type Props = { export default function BulkEditLinksModal({ onClose }: Props) { const { t } = useTranslation(); - const { updateLinks, selectedLinks, setSelectedLinks } = useLinkStore(); + const { selectedLinks, setSelectedLinks } = useLinkStore(); const [submitLoader, setSubmitLoader] = useState(false); const [removePreviousTags, setRemovePreviousTags] = useState(false); const [updatedValues, setUpdatedValues] = useState< Pick >({ tags: [] }); + const updateLinks = useBulkEditLinks(); const setCollection = (e: any) => { const collectionId = e?.value || null; setUpdatedValues((prevValues) => ({ ...prevValues, collectionId })); @@ -34,24 +36,21 @@ export default function BulkEditLinksModal({ onClose }: Props) { if (!submitLoader) { setSubmitLoader(true); - const load = toast.loading(t("updating")); - - const response = await updateLinks( - selectedLinks, - removePreviousTags, - updatedValues + await updateLinks.mutateAsync( + { + links: selectedLinks, + newData: updatedValues, + removePreviousTags, + }, + { + onSuccess: () => { + setSelectedLinks([]); + onClose(); + }, + } ); - toast.dismiss(load); - - if (response.ok) { - toast.success(t("updated")); - setSelectedLinks([]); - onClose(); - } else toast.error(response.data as string); - setSubmitLoader(false); - return response; } }; diff --git a/components/ModalContent/PreservedFormatsModal.tsx b/components/ModalContent/PreservedFormatsModal.tsx index 3d2e29d..7cd1df0 100644 --- a/components/ModalContent/PreservedFormatsModal.tsx +++ b/components/ModalContent/PreservedFormatsModal.tsx @@ -23,16 +23,14 @@ import { useGetLink } from "@/hooks/store/links"; type Props = { onClose: Function; - activeLink: LinkIncludingShortenedCollectionAndTags; + link: LinkIncludingShortenedCollectionAndTags; }; -export default function PreservedFormatsModal({ onClose, activeLink }: Props) { +export default function PreservedFormatsModal({ onClose, link }: Props) { const { t } = useTranslation(); const session = useSession(); const getLink = useGetLink(); const { data: user = {} } = useUser(); - const [link, setLink] = - useState(activeLink); const router = useRouter(); let isPublic = router.pathname.startsWith("/public") ? true : undefined; @@ -98,20 +96,14 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { useEffect(() => { (async () => { - const data = await getLink.mutateAsync(link.id as number); - setLink( - (data as any).response as LinkIncludingShortenedCollectionAndTags - ); + await getLink.mutateAsync(link.id as number); })(); let interval: any; if (!isReady()) { interval = setInterval(async () => { - const data = await getLink.mutateAsync(link.id as number); - setLink( - (data as any).response as LinkIncludingShortenedCollectionAndTags - ); + await getLink.mutateAsync(link.id as number); }, 5000); } else { if (interval) { @@ -137,10 +129,8 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { toast.dismiss(load); if (response.ok) { - const newLink = await getLink.mutateAsync(link?.id as number); - setLink( - (newLink as any).response as LinkIncludingShortenedCollectionAndTags - ); + await getLink.mutateAsync(link?.id as number); + toast.success(t("link_being_archived")); } else toast.error(data.response); }; @@ -164,7 +154,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { name={t("webpage")} icon={"bi-filetype-html"} format={ArchivedFormat.monolith} - activeLink={link} + link={link} downloadable={true} /> ) : undefined} @@ -178,7 +168,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { ? ArchivedFormat.png : ArchivedFormat.jpeg } - activeLink={link} + link={link} downloadable={true} /> ) : undefined} @@ -188,7 +178,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { name={t("pdf")} icon={"bi-file-earmark-pdf"} format={ArchivedFormat.pdf} - activeLink={link} + link={link} downloadable={true} /> ) : undefined} @@ -198,7 +188,7 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) { name={t("readable")} icon={"bi-file-earmark-text"} format={ArchivedFormat.readability} - activeLink={link} + link={link} /> ) : undefined} diff --git a/components/PreserverdFormatRow.tsx b/components/PreserverdFormatRow.tsx index 2e18e39..e8ddbd1 100644 --- a/components/PreserverdFormatRow.tsx +++ b/components/PreserverdFormatRow.tsx @@ -1,4 +1,3 @@ -import React, { useEffect, useState } from "react"; import { ArchivedFormat, LinkIncludingShortenedCollectionAndTags, @@ -11,7 +10,7 @@ type Props = { name: string; icon: string; format: ArchivedFormat; - activeLink: LinkIncludingShortenedCollectionAndTags; + link: LinkIncludingShortenedCollectionAndTags; downloadable?: boolean; }; @@ -19,47 +18,15 @@ export default function PreservedFormatRow({ name, icon, format, - activeLink, + link, downloadable, }: Props) { const getLink = useGetLink(); - const [link, setLink] = - useState(activeLink); - const router = useRouter(); let isPublic = router.pathname.startsWith("/public") ? true : undefined; - useEffect(() => { - (async () => { - const data = await getLink.mutateAsync(link.id as number); - setLink( - (data as any).response as LinkIncludingShortenedCollectionAndTags - ); - })(); - - let interval: any; - if (link?.image === "pending" || link?.pdf === "pending") { - interval = setInterval(async () => { - const data = await getLink.mutateAsync(link.id as number); - setLink( - (data as any).response as LinkIncludingShortenedCollectionAndTags - ); - }, 5000); - } else { - if (interval) { - clearInterval(interval); - } - } - - return () => { - if (interval) { - clearInterval(interval); - } - }; - }, [link?.image, link?.pdf, link?.readable, link?.monolith]); - const handleDownload = () => { const path = `/api/v1/archives/${link?.id}?format=${format}`; fetch(path) diff --git a/hooks/store/links.tsx b/hooks/store/links.tsx index 93b9b75..2fd7c2b 100644 --- a/hooks/store/links.tsx +++ b/hooks/store/links.tsx @@ -129,7 +129,7 @@ const useAddLink = () => { return [data, ...oldData]; }); - queryClient.setQueryData(["links"], (oldData: any) => { + queryClient.setQueriesData({ queryKey: ["links"] }, (oldData: any) => { if (!oldData) return undefined; return { pages: [[data, ...oldData?.pages[0]], ...oldData?.pages.slice(1)], @@ -179,13 +179,12 @@ const useUpdateLink = () => { return oldData.map((e: any) => (e.id === data.id ? data : e)); }); - queryClient.setQueryData(["links"], (oldData: any) => { + queryClient.setQueriesData({ queryKey: ["links"] }, (oldData: any) => { if (!oldData) return undefined; return { - pages: [ - oldData.pages[0].map((e: any) => (e.id === data.id ? data : e)), - ...oldData.pages.slice(1), - ], + pages: oldData.pages.map((page: any) => + page.map((item: any) => (item.id === data.id ? data : item)) + ), pageParams: oldData.pageParams, }; }); @@ -228,13 +227,12 @@ const useDeleteLink = () => { return oldData.filter((e: any) => e.id !== data.id); }); - queryClient.setQueryData(["links"], (oldData: any) => { + queryClient.setQueriesData({ queryKey: ["links"] }, (oldData: any) => { if (!oldData) return undefined; return { - pages: [ - oldData.pages[0].filter((e: any) => e.id !== data.id), - ...oldData.pages.slice(1), - ], + pages: oldData.pages.map((page: any) => + page.filter((item: any) => item.id !== data.id) + ), pageParams: oldData.pageParams, }; }); @@ -267,13 +265,12 @@ const useGetLink = () => { return oldData.map((e: any) => (e.id === data.id ? data : e)); }); - queryClient.setQueryData(["links"], (oldData: any) => { + queryClient.setQueriesData({ queryKey: ["links"] }, (oldData: any) => { if (!oldData) return undefined; return { - pages: [ - oldData.pages[0].map((e: any) => (e.id === data.id ? data : e)), - ...oldData.pages.slice(1), - ], + pages: oldData.pages.map((page: any) => + page.map((item: any) => (item.id === data.id ? data : item)) + ), pageParams: oldData.pageParams, }; }); @@ -315,13 +312,12 @@ const useBulkDeleteLinks = () => { return oldData.filter((e: any) => !data.includes(e.id)); }); - queryClient.setQueryData(["links"], (oldData: any) => { + queryClient.setQueriesData({ queryKey: ["links"] }, (oldData: any) => { if (!oldData) return undefined; return { - pages: [ - oldData.pages[0].filter((e: any) => !data.includes(e.id)), - ...oldData.pages.slice(1), - ], + pages: oldData.pages.map((page: any) => + page.filter((item: any) => !data.includes(item.id)) + ), pageParams: oldData.pageParams, }; }); @@ -401,7 +397,7 @@ const useUploadFile = () => { return [data, ...oldData]; }); - queryClient.setQueryData(["links"], (oldData: any) => { + queryClient.setQueriesData({ queryKey: ["links"] }, (oldData: any) => { if (!oldData) return undefined; return { pages: [[data, ...oldData?.pages[0]], ...oldData?.pages.slice(1)], @@ -454,7 +450,7 @@ const useBulkEditLinks = () => { return data.response; }, - onSuccess: (data) => { + onSuccess: (data, { links, newData, removePreviousTags }) => { toast.success(t("updated")); queryClient.setQueryData(["dashboardData"], (oldData: any) => { @@ -464,18 +460,18 @@ const useBulkEditLinks = () => { ); }); - queryClient.setQueryData(["links"], (oldData: any) => { - if (!oldData) return undefined; - return { - pages: [ - oldData.pages[0].map((e: any) => - data.find((d: any) => d.id === e.id) ? data : e - ), - ...oldData.pages.slice(1), - ], - pageParams: oldData.pageParams, - }; - }); + // TODO: Fix this + // queryClient.setQueriesData({ queryKey: ["links"] }, (oldData: any) => { + // if (!oldData) return undefined; + // return { + // pages: oldData.pages.map((page: any) => for (item of links) { + // page.map((item: any) => (item.id === data.id ? data : item)) + // } + // ), + // pageParams: oldData.pageParams, + // }; + // }); + queryClient.invalidateQueries({ queryKey: ["links"] }); // Temporary workaround queryClient.invalidateQueries({ queryKey: ["collections"] }); queryClient.invalidateQueries({ queryKey: ["tags"] }); diff --git a/package.json b/package.json index f25c334..f2a357e 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "react-intersection-observer": "^9.13.0", "react-masonry-css": "^1.0.16", "react-select": "^5.7.4", - "react-spinners": "^0.13.8", + "react-spinners": "^0.14.1", "socks-proxy-agent": "^8.0.2", "stripe": "^12.13.0", "tailwind-merge": "^2.3.0", diff --git a/yarn.lock b/yarn.lock index 1aecfae..edf5040 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5340,10 +5340,10 @@ react-select@^5.7.4: react-transition-group "^4.3.0" use-isomorphic-layout-effect "^1.1.2" -react-spinners@^0.13.8: - version "0.13.8" - resolved "https://registry.yarnpkg.com/react-spinners/-/react-spinners-0.13.8.tgz#5262571be0f745d86bbd49a1e6b49f9f9cb19acc" - integrity sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA== +react-spinners@^0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/react-spinners/-/react-spinners-0.14.1.tgz#de7d7d6b3e6d4f29d9620c65495b502c7dd90812" + integrity sha512-2Izq+qgQ08HTofCVEdcAQCXFEYfqTDdfeDQJeo/HHQiQJD4imOicNLhkfN2eh1NYEWVOX4D9ok2lhuDB0z3Aag== react-style-singleton@^2.2.1: version "2.2.1"