Create part-of collection card

This commit is contained in:
Zoe Roux
2026-02-19 13:41:37 +01:00
parent 01f5b44b60
commit 31af752e2e
18 changed files with 264 additions and 197 deletions
+42 -1
View File
@@ -41,6 +41,8 @@ import {
getEntryTransQ,
mapProgress,
} from "../entries";
import { Collection } from "~/models/collections";
import { alias } from "drizzle-orm/pg-core";
export const watchStatusQ = db
.select({
@@ -124,6 +126,42 @@ export const showRelations = {
.where(eq(showTranslations.pk, shows.pk))
.as("translations");
},
collection: ({
languages,
preferOriginal,
}: {
languages: string[];
preferOriginal?: boolean;
}) => {
const collections = alias(shows, "collections");
const colTrans = alias(showTranslations, "col_trans");
const transQ = db
.selectDistinctOn([colTrans.pk])
.from(colTrans)
.orderBy(
colTrans.pk,
sql`array_position(${sqlarr(languages)}, ${colTrans.language})`,
)
.as("t");
return db
.select({
json: jsonbBuildObject<Collection>({
...getColumns(collections),
...getColumns(transQ),
...(preferOriginal && {
poster: sql<Image>`coalesce(nullif(${collections.original}->'poster', 'null'::jsonb), ${transQ.poster})`,
thumbnail: sql<Image>`coalesce(nullif(${collections.original}->'thumbnail', 'null'::jsonb), ${transQ.thumbnail})`,
banner: sql<Image>`coalesce(nullif(${collections.original}->'banner', 'null'::jsonb), ${transQ.banner})`,
logo: sql<Image>`coalesce(nullif(${collections.original}->'logo', 'null'::jsonb), ${transQ.logo})`,
}),
}),
})
.from(collections)
.innerJoin(transQ, eq(collections.pk, transQ.pk))
.where(eq(collections.pk, shows.collectionPk))
.as("collection");
},
studios: ({ languages }: { languages: string[] }) => {
const studioTransQ = db
.selectDistinctOn([studioTranslations.pk])
@@ -304,7 +342,10 @@ export async function getShows({
watchStatus: getColumns(watchStatusQ),
...buildRelations(relations, showRelations, { languages }),
...buildRelations(relations, showRelations, {
languages,
preferOriginal,
}),
})
.from(shows)
.leftJoin(watchStatusQ, eq(shows.pk, watchStatusQ.showPk))
+14 -8
View File
@@ -77,10 +77,13 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
preferOriginal: t.Optional(
t.Boolean({ description: desc.preferOriginal }),
),
with: t.Array(t.UnionEnum(["translations", "studios", "videos"]), {
default: [],
description: "Include related resources in the response.",
}),
with: t.Array(
t.UnionEnum(["translations", "collection", "studios", "videos"]),
{
default: [],
description: "Include related resources in the response.",
},
),
}),
headers: t.Object({
"accept-language": AcceptLanguage(),
@@ -119,10 +122,13 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
preferOriginal: t.Optional(
t.Boolean({ description: desc.preferOriginal }),
),
with: t.Array(t.UnionEnum(["translations", "studios", "videos"]), {
default: [],
description: "Include related resources in the response.",
}),
with: t.Array(
t.UnionEnum(["translations", "collection", "studios", "videos"]),
{
default: [],
description: "Include related resources in the response.",
},
),
}),
response: {
302: t.Void({
+14 -2
View File
@@ -78,7 +78,13 @@ export const series = new Elysia({ prefix: "/series", tags: ["series"] })
t.Boolean({ description: desc.preferOriginal }),
),
with: t.Array(
t.UnionEnum(["translations", "studios", "firstEntry", "nextEntry"]),
t.UnionEnum([
"translations",
"collection",
"studios",
"firstEntry",
"nextEntry",
]),
{
default: [],
description: "Include related resources in the response.",
@@ -123,7 +129,13 @@ export const series = new Elysia({ prefix: "/series", tags: ["series"] })
t.Boolean({ description: desc.preferOriginal }),
),
with: t.Array(
t.UnionEnum(["translations", "studios", "firstEntry", "nextEntry"]),
t.UnionEnum([
"translations",
"collection",
"studios",
"firstEntry",
"nextEntry",
]),
{
default: [],
description: "Include related resources in the response.",
+2 -1
View File
@@ -1,6 +1,6 @@
import { t } from "elysia";
import type { Prettify } from "~/utils";
import { SeedCollection } from "./collections";
import { Collection, SeedCollection } from "./collections";
import { bubble, bubbleImages, registerExamples } from "./examples";
import { SeedStaff } from "./staff";
import { SeedStudio, Studio } from "./studio";
@@ -70,6 +70,7 @@ export const FullMovie = t.Intersect([
t.Object({
translations: t.Optional(TranslationRecord(MovieTranslation)),
videos: t.Optional(t.Array(EmbeddedVideo)),
collection: t.Optional(t.Nullable(Collection)),
studios: t.Optional(t.Array(Studio)),
}),
]);
+2 -1
View File
@@ -1,6 +1,6 @@
import { t } from "elysia";
import type { Prettify } from "~/utils";
import { SeedCollection } from "./collections";
import { Collection, SeedCollection } from "./collections";
import { Entry, SeedEntry, SeedExtra } from "./entry";
import { bubbleImages, madeInAbyss, registerExamples } from "./examples";
import { SeedSeason } from "./season";
@@ -84,6 +84,7 @@ export const FullSerie = t.Intersect([
Serie,
t.Object({
translations: t.Optional(TranslationRecord(SerieTranslation)),
collection: t.Optional(t.Nullable(Collection)),
studios: t.Optional(t.Array(Studio)),
firstEntry: t.Optional(t.Nullable(Entry)),
nextEntry: t.Optional(t.Nullable(Entry)),