Fix moving of tags table

This commit is contained in:
2026-02-02 15:18:26 +01:00
parent 9121b74ade
commit 1a855b2177
3 changed files with 123 additions and 61 deletions

View File

@ -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[]

View File

@ -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<string, typeof tags>();
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<string, typeof tagsWithParents>();
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);

View File

@ -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<string, typeof tagsForFilter>();
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 (