From abb73f80bd5da7efa15508b8ee29a87cd061c957 Mon Sep 17 00:00:00 2001 From: Oliver Schwamb Date: Wed, 10 Jul 2024 10:22:58 +0200 Subject: [PATCH] Reworked access to tags as public viewer --- hooks/useLinks.tsx | 11 +----- .../links/getPublicLinksUnderCollection.ts | 4 +-- lib/api/controllers/tags/getTags.ts | 2 +- pages/api/v1/public/collections/tags/index.ts | 35 +++++++++++++++++++ pages/public/collections/[id].tsx | 15 ++++---- store/links.ts | 4 --- store/tags.ts | 10 ++++-- 7 files changed, 52 insertions(+), 29 deletions(-) create mode 100644 pages/api/v1/public/collections/tags/index.ts diff --git a/hooks/useLinks.tsx b/hooks/useLinks.tsx index 6d0e935..c14d0c9 100644 --- a/hooks/useLinks.tsx +++ b/hooks/useLinks.tsx @@ -18,7 +18,7 @@ export default function useLinks( searchByTextContent, }: LinkRequestQuery = { sort: 0 } ) { - const { links, setLinks, resetLinks, selectedLinks, setSelectedLinks, setAllLinksOfCollection } = + const { links, setLinks, resetLinks, selectedLinks, setSelectedLinks } = useLinkStore(); const router = useRouter(); @@ -80,14 +80,6 @@ export default function useLinks( if (response.ok) setLinks(data.response, isInitialCall); }; - const getAllLinks = async () => { - const response = await fetch(getPath()); - - const data = await response.json(); - - if (response.ok) setAllLinksOfCollection(data.response); - }; - useEffect(() => { // Save the selected links before resetting the links // and then restore the selected links after resetting the links @@ -95,7 +87,6 @@ export default function useLinks( resetLinks(); setSelectedLinks(previouslySelected); - getAllLinks(); getLinks(true); }, [ router, diff --git a/lib/api/controllers/public/links/getPublicLinksUnderCollection.ts b/lib/api/controllers/public/links/getPublicLinksUnderCollection.ts index e94a3e1..5f59fd0 100644 --- a/lib/api/controllers/public/links/getPublicLinksUnderCollection.ts +++ b/lib/api/controllers/public/links/getPublicLinksUnderCollection.ts @@ -2,7 +2,7 @@ import { prisma } from "@/lib/api/db"; import { LinkRequestQuery, Sort } from "@/types/global"; export default async function getLink( - query: Omit + query: Omit, takeAll = false ) { const POSTGRES_IS_ENABLED = process.env.DATABASE_URL.startsWith("postgresql"); @@ -68,7 +68,7 @@ export default async function getLink( } const links = await prisma.link.findMany({ - take: Number(process.env.PAGINATION_TAKE_COUNT) || 20, + take: !takeAll ? Number(process.env.PAGINATION_TAKE_COUNT) || 20 : undefined, skip: query.cursor ? 1 : undefined, cursor: query.cursor ? { id: query.cursor } : undefined, where: { diff --git a/lib/api/controllers/tags/getTags.ts b/lib/api/controllers/tags/getTags.ts index 85a8d17..65fb446 100644 --- a/lib/api/controllers/tags/getTags.ts +++ b/lib/api/controllers/tags/getTags.ts @@ -1,6 +1,6 @@ import { prisma } from "@/lib/api/db"; -export default async function getTags(userId: number) { +export default async function getTags(userId?: number) { // Remove empty tags await prisma.tag.deleteMany({ where: { diff --git a/pages/api/v1/public/collections/tags/index.ts b/pages/api/v1/public/collections/tags/index.ts new file mode 100644 index 0000000..fae93bd --- /dev/null +++ b/pages/api/v1/public/collections/tags/index.ts @@ -0,0 +1,35 @@ +import getPublicLinksUnderCollection from "@/lib/api/controllers/public/links/getPublicLinksUnderCollection"; +import getTags from "@/lib/api/controllers/tags/getTags"; +import { LinkRequestQuery } from "@/types/global"; +import type { NextApiRequest, NextApiResponse } from "next"; + +export default async function collections( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method === "GET") { + // Convert the type of the request query to "LinkRequestQuery" + const convertedData: Omit = { + sort: Number(req.query.sort as string), + collectionId: req.query.collectionId + ? Number(req.query.collectionId as string) + : undefined, + }; + + if (!convertedData.collectionId) { + return res + .status(400) + .json({ response: "Please choose a valid collection." }); + } + + const links = await getPublicLinksUnderCollection(convertedData, true); + const tags = await getTags(); + const tagsInLinks = links.response.map(l => l.tags).flat().filter((value, index, self) => + index === self.findIndex((t) => ( + t.name === value.name + ))).map(t => t.id); + const tagsWithCount = tags.response.filter(tag => tagsInLinks.includes(tag.id)); + + return res.status(links.status).json({ response: tagsWithCount }); + } +} diff --git a/pages/public/collections/[id].tsx b/pages/public/collections/[id].tsx index 18c69dc..4e51724 100644 --- a/pages/public/collections/[id].tsx +++ b/pages/public/collections/[id].tsx @@ -44,11 +44,7 @@ const cardVariants: Variants = { }; export default function PublicCollections() { - const { links, allLinksOfCollection } = useLinkStore(); - const tagsInCollection = allLinksOfCollection.map(l => l.tags).flat().filter((value, index, self) => - index === self.findIndex((t) => ( - t.name === value.name - ))); + const { links } = useLinkStore(); const { settings } = useLocalSettingsStore(); const router = useRouter(); @@ -62,7 +58,7 @@ export default function PublicCollections() { archiveAsPDF: undefined as unknown as boolean, }); - const { tags } = useTagStore(); + const { tags, setTags } = useTagStore(); const handleTagSelection = (tag: TagIncludingLinkCount | undefined) => { if (tag) { Object.keys(searchFilter).forEach((v) => searchFilter[(v as keyof {name: boolean, url: boolean, description: boolean, tags: boolean, textContent: boolean})] = false) @@ -107,6 +103,7 @@ export default function PublicCollections() { useEffect(() => { if (router.query.id) { getPublicCollectionData(Number(router.query.id), setCollection); + setTags(Number(router.query.id)) } }, []); @@ -252,7 +249,7 @@ export default function PublicCollections() { -{collection.tagsArePublic && tagsInCollection[0] && ( +{collection.tagsArePublic && tags[0] && ( { @@ -289,7 +286,7 @@ export default function PublicCollections() { - {tagsInCollection + {tags .sort((a, b) => a.name.localeCompare(b.name)) .map((e, i) => { const active = router.query.q === e.name; @@ -306,7 +303,7 @@ export default function PublicCollections() {

{e.name}

- {tags.find(t => t.id === e.id)?._count?.links} + {e._count?.links}
diff --git a/store/links.ts b/store/links.ts index 8391f55..408a3ee 100644 --- a/store/links.ts +++ b/store/links.ts @@ -11,13 +11,11 @@ type ResponseObject = { type LinkStore = { links: LinkIncludingShortenedCollectionAndTags[]; selectedLinks: LinkIncludingShortenedCollectionAndTags[]; - allLinksOfCollection: LinkIncludingShortenedCollectionAndTags[]; setLinks: ( data: LinkIncludingShortenedCollectionAndTags[], isInitialCall: boolean ) => void; setSelectedLinks: (links: LinkIncludingShortenedCollectionAndTags[]) => void; - setAllLinksOfCollection: (links: LinkIncludingShortenedCollectionAndTags[]) => void; addLink: ( body: LinkIncludingShortenedCollectionAndTags ) => Promise; @@ -41,7 +39,6 @@ type LinkStore = { const useLinkStore = create()((set) => ({ links: [], selectedLinks: [], - allLinksOfCollection: [], setLinks: async (data, isInitialCall) => { isInitialCall && set(() => ({ @@ -61,7 +58,6 @@ const useLinkStore = create()((set) => ({ })); }, setSelectedLinks: (links) => set({ selectedLinks: links }), - setAllLinksOfCollection: (links) => set({allLinksOfCollection: links}), addLink: async (body) => { const response = await fetch("/api/v1/links", { body: JSON.stringify(body), diff --git a/store/tags.ts b/store/tags.ts index 6778152..f8a0337 100644 --- a/store/tags.ts +++ b/store/tags.ts @@ -8,15 +8,19 @@ type ResponseObject = { type TagStore = { tags: TagIncludingLinkCount[]; - setTags: () => void; + setTags: (collectionId?: number) => void; updateTag: (tag: TagIncludingLinkCount) => Promise; removeTag: (tagId: number) => Promise; }; const useTagStore = create()((set) => ({ tags: [], - setTags: async () => { - const response = await fetch("/api/v1/tags"); + setTags: async (collectionId?: number) => { + let path = "/api/v1/tags"; + if (collectionId) { + path = "/api/v1/public/collections/tags?collectionId=" + encodeURIComponent(collectionId); + } + const response = await fetch(path); const data = await response.json();