From 1a855b2177ffb09f64d036047fec052c21b248bc Mon Sep 17 00:00:00 2001 From: Citali Date: Mon, 2 Feb 2026 15:18:26 +0100 Subject: [PATCH] Fix moving of tags table --- prisma/schema.prisma | 107 +++++++++++------- .../artworks/animalstudies/index/page.tsx | 29 +++-- .../(normal)/artworks/animalstudies/page.tsx | 48 +++++--- 3 files changed, 123 insertions(+), 61 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e896983..eb52aa8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -53,7 +53,7 @@ model Artwork { albums Album[] categories ArtCategory[] colors ArtworkColor[] - tags ArtTag[] + tags Tag[] @relation("ArtworkTags") variants FileVariant[] @@index([colorStatus]) @@ -101,43 +101,7 @@ model ArtCategory { description String? artworks Artwork[] - tags ArtTag[] -} - -model ArtTag { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - sortIndex Int @default(0) - - name String @unique - slug String @unique - isParent Boolean @default(false) - showOnAnimalPage Boolean @default(false) - - description String? - - aliases ArtTagAlias[] - artworks Artwork[] - categories ArtCategory[] - - parentId String? - parent ArtTag? @relation("TagHierarchy", fields: [parentId], references: [id], onDelete: SetNull) - children ArtTag[] @relation("TagHierarchy") -} - -model ArtTagAlias { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - alias String @unique - - tagId String - tag ArtTag @relation(fields: [tagId], references: [id], onDelete: Cascade) - - @@unique([tagId, alias]) - @@index([alias]) + tagLinks TagCategory[] } model Color { @@ -248,6 +212,71 @@ model FileVariant { @@unique([artworkId, type]) } +model Tag { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + name String @unique + slug String @unique + isVisible Boolean @default(true) + + description String? + + aliases TagAlias[] + categoryLinks TagCategory[] + categoryParents TagCategory[] @relation("TagCategoryParent") + artworks Artwork[] @relation("ArtworkTags") + commissionTypes CommissionType[] @relation("CommissionTypeTags") + miniatures Miniature[] @relation("MiniatureTags") +} + +model TagAlias { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + alias String @unique + + tagId String + tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) + + @@unique([tagId, alias]) + @@index([alias]) +} + +model TagCategory { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + tagId String + categoryId String + + isParent Boolean @default(false) + showOnAnimalPage Boolean @default(false) + parentTagId String? + + tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) + category ArtCategory @relation(fields: [categoryId], references: [id], onDelete: Cascade) + parentTag Tag? @relation("TagCategoryParent", fields: [parentTagId], references: [id], onDelete: SetNull) + + @@unique([tagId, categoryId]) + @@index([categoryId]) + @@index([tagId]) + @@index([parentTagId]) + @@index([categoryId, parentTagId]) +} + +model Miniature { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + tags Tag[] @relation("MiniatureTags") +} + model Commission { id String @id @default(cuid()) createdAt DateTime @default(now()) @@ -265,6 +294,8 @@ model CommissionType { description String? + tags Tag[] @relation("CommissionTypeTags") + options CommissionTypeOption[] extras CommissionTypeExtra[] customInputs CommissionTypeCustomInput[] diff --git a/src/app/(normal)/artworks/animalstudies/index/page.tsx b/src/app/(normal)/artworks/animalstudies/index/page.tsx index 876503a..cd741da 100644 --- a/src/app/(normal)/artworks/animalstudies/index/page.tsx +++ b/src/app/(normal)/artworks/animalstudies/index/page.tsx @@ -30,14 +30,22 @@ function sortArtworks(a: SimpleArtwork, b: SimpleArtwork) { } export default async function AnimalListPage() { - const tags = await prisma.artTag.findMany({ - where: { showOnAnimalPage: true }, + const tags = await prisma.tag.findMany({ + where: { + isVisible: true, + categoryLinks: { + some: { category: { name: "Animal Studies" }, showOnAnimalPage: true }, + }, + }, select: { id: true, name: true, slug: true, sortIndex: true, - parentId: true, + categoryLinks: { + where: { category: { name: "Animal Studies" } }, + select: { parentTagId: true }, + }, artworks: { where: { published: true, @@ -50,10 +58,15 @@ export default async function AnimalListPage() { orderBy: [{ sortIndex: "asc" }, { name: "asc" }], }); - const byId = new Map(tags.map((t) => [t.id, t])); - const childrenByParentId = new Map(); + const tagsWithParents = tags.map((t) => ({ + ...t, + parentId: t.categoryLinks[0]?.parentTagId ?? null, + })); - for (const t of tags) { + const byId = new Map(tagsWithParents.map((t) => [t.id, t])); + const childrenByParentId = new Map(); + + for (const t of tagsWithParents) { if (!t.parentId) continue; const arr = childrenByParentId.get(t.parentId) ?? []; arr.push(t); @@ -64,12 +77,12 @@ export default async function AnimalListPage() { childrenByParentId.set(pid, arr.slice().sort(sortBySortIndexName)); } - const parents = tags + const parents = tagsWithParents .filter((t) => t.parentId === null) .slice() .sort(sortBySortIndexName); - const orphans = tags + const orphans = tagsWithParents .filter((t) => t.parentId !== null && !byId.has(t.parentId)) .slice() .sort(sortBySortIndexName); diff --git a/src/app/(normal)/artworks/animalstudies/page.tsx b/src/app/(normal)/artworks/animalstudies/page.tsx index 09561ae..a4c101d 100644 --- a/src/app/(normal)/artworks/animalstudies/page.tsx +++ b/src/app/(normal)/artworks/animalstudies/page.tsx @@ -17,17 +17,28 @@ function parseTagsParam(tags: string | string[] | undefined): string[] { function expandSelectedWithChildren( selectedSlugs: string[], tagsForFilter: Array<{ + id: string; slug: string; - children: Array<{ slug: string }>; + parentId: string | null; }>, ) { const bySlug = new Map(tagsForFilter.map((t) => [t.slug, t])); + const childrenByParentId = new Map(); + + for (const t of tagsForFilter) { + if (!t.parentId) continue; + const arr = childrenByParentId.get(t.parentId) ?? []; + arr.push(t); + childrenByParentId.set(t.parentId, arr); + } + const out = new Set(selectedSlugs); for (const slug of selectedSlugs) { const t = bySlug.get(slug); if (!t) continue; - for (const c of t.children ?? []) out.add(c.slug); + const children = childrenByParentId.get(t.id) ?? []; + for (const c of children) out.add(c.slug); } return Array.from(out); @@ -41,24 +52,31 @@ export default async function AnimalStudiesPage({ const { tags } = await searchParams; const selectedTagSlugs = parseTagsParam(tags); - const tagsForFilter = await prisma.artTag.findMany({ - where: { showOnAnimalPage: true }, + const tagLinks = await prisma.tagCategory.findMany({ + where: { + showOnAnimalPage: true, + category: { name: "Animal Studies" }, + tag: { isVisible: true }, + }, select: { - id: true, - name: true, - slug: true, - sortIndex: true, - parentId: true, - parent: { select: { id: true, name: true, slug: true, sortIndex: true } }, - children: { - where: { showOnAnimalPage: true }, - select: { id: true, name: true, slug: true, sortIndex: true, parentId: true }, - orderBy: [{ sortIndex: "asc" }, { name: "asc" }], + parentTagId: true, + tag: { + select: { id: true, name: true, slug: true, sortIndex: true }, }, }, - orderBy: [{ sortIndex: "asc" }, { name: "asc" }], + orderBy: [{ tag: { sortIndex: "asc" } }, { tag: { name: "asc" } }], }); + const tagsForFilter = tagLinks.map((link) => ({ + id: link.tag.id, + name: link.tag.name, + slug: link.tag.slug, + sortIndex: link.tag.sortIndex, + parentId: link.parentTagId, + parent: null, + children: [], + })); + const expandedTagSlugs = expandSelectedWithChildren(selectedTagSlugs, tagsForFilter); return (