From 92f6ee39427e742f76345ccf64f3c495b9c8b17a Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 27 Jun 2023 03:05:12 +0330 Subject: [PATCH] major bug fixed + error handling --- components/LinkCard.tsx | 30 +++++---- .../Link/{EditLink.tsx => AddOrEditLink.tsx} | 5 +- components/Modal/Link/LinkDetails.tsx | 7 +- components/Modal/Link/index.tsx | 9 ++- components/PublicPage/LinkCard.tsx | 58 +++++++++-------- lib/api/controllers/links/getLinks.ts | 64 ++++++++++--------- lib/api/getTitle.ts | 16 +++-- lib/client/isValidUrl.ts | 8 +++ pages/collections/[id].tsx | 2 + pages/public/collections/[id].tsx | 9 ++- 10 files changed, 122 insertions(+), 86 deletions(-) rename components/Modal/Link/{EditLink.tsx => AddOrEditLink.tsx} (97%) create mode 100644 lib/client/isValidUrl.ts diff --git a/components/LinkCard.tsx b/components/LinkCard.tsx index 7462056..fa28756 100644 --- a/components/LinkCard.tsx +++ b/components/LinkCard.tsx @@ -14,6 +14,7 @@ import useModalStore from "@/store/modals"; import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; import usePermissions from "@/hooks/usePermissions"; import { toast } from "react-hot-toast"; +import isValidUrl from "@/lib/client/isValidUrl"; type Props = { link: LinkIncludingShortenedCollectionAndTags; @@ -78,7 +79,8 @@ export default function LinkCard({ link, count, className }: Props) { setExpandDropdown(false); }; - const url = new URL(link.url); + const url = isValidUrl(link.url) ? new URL(link.url) : undefined; + const formattedDate = new Date(link.createdAt as string).toLocaleString( "en-US", { @@ -122,18 +124,20 @@ export default function LinkCard({ link, count, className }: Props) { }} className="flex items-start gap-5 sm:gap-10 h-full w-full p-5" > - { - const target = e.target as HTMLElement; - target.style.opacity = "0"; - }} - /> + {url && ( + { + const target = e.target as HTMLElement; + target.style.display = "none"; + }} + /> + )}
diff --git a/components/Modal/Link/EditLink.tsx b/components/Modal/Link/AddOrEditLink.tsx similarity index 97% rename from components/Modal/Link/EditLink.tsx rename to components/Modal/Link/AddOrEditLink.tsx index 8e3658f..d1450ef 100644 --- a/components/Modal/Link/EditLink.tsx +++ b/components/Modal/Link/AddOrEditLink.tsx @@ -24,7 +24,7 @@ type Props = activeLink: LinkIncludingShortenedCollectionAndTags; }; -export default function EditLink({ +export default function AddOrEditLink({ toggleLinkModal, method, activeLink, @@ -70,8 +70,7 @@ export default function EditLink({ } }, []); - const shortendURL = - method === "UPDATE" ? new URL(link.url).host.toLowerCase() : undefined; + // const shortendURL = method === "UPDATE" ? new URL(link.url).host.toLowerCase() : undefined; const setTags = (e: any) => { const tagNames = e.map((e: any) => { diff --git a/components/Modal/Link/LinkDetails.tsx b/components/Modal/Link/LinkDetails.tsx index 1aab780..8c8521f 100644 --- a/components/Modal/Link/LinkDetails.tsx +++ b/components/Modal/Link/LinkDetails.tsx @@ -19,6 +19,7 @@ import { faFileImage, faFilePdf, } from "@fortawesome/free-regular-svg-icons"; +import isValidUrl from "@/lib/client/isValidUrl"; type Props = { link: LinkIncludingShortenedCollectionAndTags; @@ -56,7 +57,7 @@ export default function LinkDetails({ link }: Props) { const colorThief = new ColorThief(); - const url = new URL(link.url); + const url = isValidUrl(link.url) ? new URL(link.url) : undefined; const rgbToHex = (r: number, g: number, b: number): string => "#" + @@ -123,7 +124,7 @@ export default function LinkDetails({ link }: Props) {
- {!imageError && ( + {!imageError && url && ( - {url.host} + {url ? url.host : link.url}
diff --git a/components/Modal/Link/index.tsx b/components/Modal/Link/index.tsx index 1da0562..d4b801a 100644 --- a/components/Modal/Link/index.tsx +++ b/components/Modal/Link/index.tsx @@ -1,6 +1,6 @@ import { Tab } from "@headlessui/react"; import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; -import EditLink from "./EditLink"; +import AddOrEditLink from "./AddOrEditLink"; import LinkDetails from "./LinkDetails"; type Props = @@ -72,13 +72,16 @@ export default function LinkModal({ {activeLink && method === "UPDATE" ? ( - ) : ( - + )} diff --git a/components/PublicPage/LinkCard.tsx b/components/PublicPage/LinkCard.tsx index 1b352f7..5bd2471 100644 --- a/components/PublicPage/LinkCard.tsx +++ b/components/PublicPage/LinkCard.tsx @@ -2,6 +2,7 @@ import { faChevronRight } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Image from "next/image"; import { Link as LinkType, Tag } from "@prisma/client"; +import isValidUrl from "@/lib/client/isValidUrl"; interface LinksIncludingTags extends LinkType { tags: Tag[]; @@ -13,7 +14,8 @@ type Props = { }; export default function LinkCard({ link, count }: Props) { - const url = new URL(link.url); + const url = isValidUrl(link.url) ? new URL(link.url) : undefined; + const formattedDate = new Date( link.createdAt as unknown as string ).toLocaleString("en-US", { @@ -25,30 +27,34 @@ export default function LinkCard({ link, count }: Props) { return (
- { - const target = e.target as HTMLElement; - target.style.opacity = "0"; - }} - /> - { - const target = e.target as HTMLElement; - target.style.opacity = "0"; - }} - /> + {url && ( + <> + { + const target = e.target as HTMLElement; + target.style.display = "none"; + }} + /> + { + const target = e.target as HTMLElement; + target.style.display = "none"; + }} + /> + + )}
@@ -74,7 +80,7 @@ export default function LinkCard({ link, count }: Props) {

{formattedDate}

-

{url.host}

+

{url ? url.host : link.url}

diff --git a/lib/api/controllers/links/getLinks.ts b/lib/api/controllers/links/getLinks.ts index 5c0a1ce..5358061 100644 --- a/lib/api/controllers/links/getLinks.ts +++ b/lib/api/controllers/links/getLinks.ts @@ -103,39 +103,43 @@ export default async function getLink(userId: number, body: string) { query.searchQuery && !query.searchFilter?.tags ? undefined : { - some: { - id: query.tagId ? query.tagId : undefined, // If tagId was defined, filter by tag - name: - query.searchQuery && query.searchFilter?.tags - ? { - contains: query.searchQuery, - mode: "insensitive", - } - : undefined, - OR: [ - { ownerId: userId }, // Tags owned by the user - { - links: { - some: { - name: { - contains: - query.searchQuery && query.searchFilter?.tags - ? query.searchQuery - : undefined, - mode: "insensitive", - }, - collection: { - members: { - some: { - userId, // Tags from collections where the user is a member + some: query.tagId + ? { + // If tagId was defined, filter by tag + id: query.tagId, + name: + query.searchQuery && query.searchFilter?.tags + ? { + contains: query.searchQuery, + mode: "insensitive", + } + : undefined, + OR: [ + { ownerId: userId }, // Tags owned by the user + { + links: { + some: { + name: { + contains: + query.searchQuery && + query.searchFilter?.tags + ? query.searchQuery + : undefined, + mode: "insensitive", + }, + collection: { + members: { + some: { + userId, // Tags from collections where the user is a member + }, + }, }, }, }, }, - }, - }, - ], - }, + ], + } + : undefined, }, }, ], @@ -153,5 +157,7 @@ export default async function getLink(userId: number, body: string) { }, }); + console.log(links); + return { response: links, status: 200 }; } diff --git a/lib/api/getTitle.ts b/lib/api/getTitle.ts index e654b30..5b23de7 100644 --- a/lib/api/getTitle.ts +++ b/lib/api/getTitle.ts @@ -1,9 +1,13 @@ export default async function getTitle(url: string) { - const response = await fetch(url); - const text = await response.text(); + try { + const response = await fetch(url); + const text = await response.text(); - // regular expression to find the tag - let match = text.match(/<title.*>([^<]*)<\/title>/); - if (match) return match[1] + " [AUTO GENERATED]"; - else return ""; + // regular expression to find the <title> tag + let match = text.match(/<title.*>([^<]*)<\/title>/); + if (match) return match[1] + " [AUTO GENERATED]"; + else return ""; + } catch (err) { + console.log(err); + } } diff --git a/lib/client/isValidUrl.ts b/lib/client/isValidUrl.ts new file mode 100644 index 0000000..96d192c --- /dev/null +++ b/lib/client/isValidUrl.ts @@ -0,0 +1,8 @@ +export default function isValidUrl(string: string) { + try { + new URL(string); + return true; + } catch (err) { + return false; + } +} diff --git a/pages/collections/[id].tsx b/pages/collections/[id].tsx index 7c6d688..fefc087 100644 --- a/pages/collections/[id].tsx +++ b/pages/collections/[id].tsx @@ -46,6 +46,8 @@ export default function Index() { ); }, [router, collections]); + console.log(links); + return ( <MainLayout> <div className="p-5 flex flex-col gap-5 w-full"> diff --git a/pages/public/collections/[id].tsx b/pages/public/collections/[id].tsx index f697776..2f06612 100644 --- a/pages/public/collections/[id].tsx +++ b/pages/public/collections/[id].tsx @@ -49,9 +49,12 @@ export default function PublicCollections() { {data.name} </p> - <hr className="mt-5 max-w-[30rem] mx-auto border-1 border-slate-400" /> - - <p className="mt-2 text-gray-500">{data.description}</p> + {data.description && ( + <> + <hr className="mt-5 max-w-[30rem] mx-auto border-1 border-slate-400" /> + <p className="mt-2 text-gray-500">{data.description}</p> + </> + )} </div> <div className="flex flex-col gap-5 my-8">