From 2e2d7baee1564066bb6a407829a6b1021da86481 Mon Sep 17 00:00:00 2001 From: daniel31x13 Date: Wed, 27 Mar 2024 03:20:00 -0400 Subject: [PATCH] fix imports --- .../LinkViews/LinkComponents/LinkDate.tsx | 15 +- components/ReadableView.tsx | 8 +- .../migration/importFromHTMLFile.ts | 144 +++++++++++------- .../migration.sql | 2 + prisma/schema.prisma | 1 + 5 files changed, 107 insertions(+), 63 deletions(-) create mode 100644 prisma/migrations/20240327070238_add_import_date_field_for_links/migration.sql diff --git a/components/LinkViews/LinkComponents/LinkDate.tsx b/components/LinkViews/LinkComponents/LinkDate.tsx index e512dcb..7bed676 100644 --- a/components/LinkViews/LinkComponents/LinkDate.tsx +++ b/components/LinkViews/LinkComponents/LinkDate.tsx @@ -6,14 +6,13 @@ export default function LinkDate({ }: { link: LinkIncludingShortenedCollectionAndTags; }) { - const formattedDate = new Date(link.createdAt as string).toLocaleString( - "en-US", - { - year: "numeric", - month: "short", - day: "numeric", - } - ); + const formattedDate = new Date( + (link.importDate || link.createdAt) as string + ).toLocaleString("en-US", { + year: "numeric", + month: "short", + day: "numeric", + }); return (
diff --git a/components/ReadableView.tsx b/components/ReadableView.tsx index f8eb3b6..9c7ce17 100644 --- a/components/ReadableView.tsx +++ b/components/ReadableView.tsx @@ -34,6 +34,8 @@ export default function ReadableView({ link }: Props) { const [imageError, setImageError] = useState(false); const [colorPalette, setColorPalette] = useState(); + const [date, setDate] = useState(); + const colorThief = new ColorThief(); const router = useRouter(); @@ -54,6 +56,8 @@ export default function ReadableView({ link }: Props) { }; fetchLinkContent(); + + setDate(link.importDate || link.createdAt); }, [link]); useEffect(() => { @@ -211,8 +215,8 @@ export default function ReadableView({ link }: Props) {

- {link?.createdAt - ? new Date(link?.createdAt).toLocaleString("en-US", { + {date + ? new Date(date).toLocaleString("en-US", { year: "numeric", month: "long", day: "numeric", diff --git a/lib/api/controllers/migration/importFromHTMLFile.ts b/lib/api/controllers/migration/importFromHTMLFile.ts index 833643b..21fb3c4 100644 --- a/lib/api/controllers/migration/importFromHTMLFile.ts +++ b/lib/api/controllers/migration/importFromHTMLFile.ts @@ -2,6 +2,7 @@ import { prisma } from "@/lib/api/db"; import createFolder from "@/lib/api/storage/createFolder"; import { JSDOM } from "jsdom"; import { parse, Node, Element, TextNode } from "himalaya"; +import { writeFileSync } from "fs"; const MAX_LINKS_PER_USER = Number(process.env.MAX_LINKS_PER_USER) || 30000; @@ -36,7 +37,9 @@ export default async function importFromHTMLFile( const jsonData = parse(document.documentElement.outerHTML); - for (const item of jsonData) { + const processedArray = processNodes(jsonData); + + for (const item of processedArray) { console.log(item); await processBookmarks(userId, item as Element); } @@ -74,7 +77,9 @@ async function processBookmarks( } else if (item.type === "element" && item.tagName === "a") { // process link - const linkUrl = item?.attributes.find((e) => e.key.toLowerCase() === "href")?.value; + const linkUrl = item?.attributes.find( + (e) => e.key.toLowerCase() === "href" + )?.value; const linkName = ( item?.children.find((e) => e.type === "text") as TextNode )?.content; @@ -83,30 +88,22 @@ async function processBookmarks( ?.value.split(","); // set date if available - const linkDateValue = item?.attributes.find((e) => e.key.toLowerCase() === "add_date")?.value; - let linkDate = Date.now(); - if (linkDateValue) { - try { - linkDate = Number.parseInt(linkDateValue); - // use the year 2000 as an arbitrary cutoff to determine if a link is in seconds or milliseconds - const year2000ms = 946684800000; - if ((linkDate > 0) && (linkDate < year2000ms)) { - linkDate = linkDate * 1000; // turn epoch seconds into milliseconds - } - } catch (error) { - // just ignore the error if it happens - } - } + const linkDateValue = item?.attributes.find( + (e) => e.key.toLowerCase() === "add_date" + )?.value; - let linkDesc = ""; - const descNode = data.children.find((e) => (e as Element).tagName?.toLowerCase() === "dd") as Element; - if (descNode && descNode.children.length > 0) { - try { - linkDesc = (descNode.children[0] as TextNode).content; - } catch (error) { - // just ignore the error if it happens - } - } + const linkDate = linkDateValue + ? new Date(Number(linkDateValue) * 1000) + : undefined; + + let linkDesc = + ( + ( + item?.children?.find( + (e) => e.type === "element" && e.tagName === "dd" + ) as Element + )?.children[0] as TextNode + )?.content || ""; if (linkUrl && parentCollectionId) { await createLink( @@ -164,10 +161,10 @@ const createCollection = async ( name: collectionName, parent: parentId ? { - connect: { - id: parentId, - }, - } + connect: { + id: parentId, + }, + } : undefined, owner: { connect: { @@ -189,40 +186,81 @@ const createLink = async ( name?: string, description?: string, tags?: string[], - createdAt?: number, + importDate?: Date ) => { await prisma.link.create({ data: { name: name || "", - type: url, - description: description, - collectionId: collectionId, + url, + description, + collectionId, tags: tags && tags[0] ? { - connectOrCreate: tags.map((tag: string) => { - return ( - { - where: { - name_ownerId: { - name: tag.trim(), - ownerId: userId, - }, - }, - create: { - name: tag.trim(), - owner: { - connect: { - id: userId, + connectOrCreate: tags.map((tag: string) => { + return ( + { + where: { + name_ownerId: { + name: tag.trim(), + ownerId: userId, }, }, - }, - } || undefined - ); - }), - } + create: { + name: tag.trim(), + owner: { + connect: { + id: userId, + }, + }, + }, + } || undefined + ); + }), + } : undefined, - createdAt: createdAt + importDate: importDate || undefined, }, }); }; + +function processNodes(nodes: Node[]) { + const findAndProcessDL = (node: Node) => { + if (node.type === "element" && node.tagName === "dl") { + processDLChildren(node); + } else if ( + node.type === "element" && + node.children && + node.children.length + ) { + node.children.forEach((child) => findAndProcessDL(child)); + } + }; + + const processDLChildren = (dlNode: Element) => { + dlNode.children.forEach((child, i) => { + if (child.type === "element" && child.tagName === "dt") { + const nextSibling = dlNode.children[i + 1]; + if ( + nextSibling && + nextSibling.type === "element" && + nextSibling.tagName === "dd" + ) { + const aElement = child.children.find( + (el) => el.type === "element" && el.tagName === "a" + ); + if (aElement && aElement.type === "element") { + // Add the 'dd' element as a child of the 'a' element + aElement.children.push(nextSibling); + // Remove the 'dd' from the parent 'dl' to avoid duplicate processing + dlNode.children.splice(i + 1, 1); + // Adjust the loop counter due to the removal + } + } + } + }); + }; + + nodes.forEach(findAndProcessDL); + return nodes; +} diff --git a/prisma/migrations/20240327070238_add_import_date_field_for_links/migration.sql b/prisma/migrations/20240327070238_add_import_date_field_for_links/migration.sql new file mode 100644 index 0000000..7ebb1fe --- /dev/null +++ b/prisma/migrations/20240327070238_add_import_date_field_for_links/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Link" ADD COLUMN "importDate" TIMESTAMP(3); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index da73115..26d6dc9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -128,6 +128,7 @@ model Link { pdf String? readable String? lastPreserved DateTime? + importDate DateTime? createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt }