diff --git a/src/app/zxdb/entries/[id]/EntryDetail.tsx b/src/app/zxdb/entries/[id]/EntryDetail.tsx
index f6b685a..50e9348 100644
--- a/src/app/zxdb/entries/[id]/EntryDetail.tsx
+++ b/src/app/zxdb/entries/[id]/EntryDetail.tsx
@@ -22,6 +22,14 @@ export type EntryDetailData = {
linkSite?: string | null;
comments?: string | null;
}[];
+ origins?: {
+ type: { id: string; name: string | null };
+ libraryTitle: string;
+ publication: string | null;
+ containerId: number | null;
+ issueId: number | null;
+ date: { year: number | null; month: number | null; day: number | null };
+ }[];
// extra fields for richer details
maxPlayers?: number;
availabletypeId?: string | null;
@@ -340,6 +348,53 @@ export default function EntryDetailClient({ data }: { data: EntryDetailData | nu
+
Origins
+ {(!data.origins || data.origins.length === 0) &&
No origins recorded
}
+ {data.origins && data.origins.length > 0 && (
+
+
+
+
+ | Type |
+ Title |
+ Publication |
+ Issue |
+ Date |
+
+
+
+ {data.origins.map((o, idx) => {
+ const dateParts = [o.date.year, o.date.month, o.date.day]
+ .filter((v) => typeof v === "number" && Number.isFinite(v))
+ .map((v, i) => (i === 0 ? String(v) : String(v).padStart(2, "0")));
+ const dateText = dateParts.length ? dateParts.join("/") : "-";
+ return (
+
+ | {o.type.name ?? o.type.id} |
+ {o.libraryTitle} |
+ {o.publication ?? -} |
+
+ {o.issueId ? (
+ #{o.issueId}
+ ) : o.containerId ? (
+ #{o.containerId}
+ ) : (
+ -
+ )}
+ |
+ {dateText} |
+
+ );
+ })}
+
+
+
+ )}
+
+
+
Aliases
diff --git a/src/app/zxdb/labels/[id]/LabelDetail.tsx b/src/app/zxdb/labels/[id]/LabelDetail.tsx
index bc95b70..9f71d4d 100644
--- a/src/app/zxdb/labels/[id]/LabelDetail.tsx
+++ b/src/app/zxdb/labels/[id]/LabelDetail.tsx
@@ -9,6 +9,7 @@ type Label = {
id: number;
name: string;
labeltypeId: string | null;
+ labeltypeName: string | null;
permissions: {
website: { id: number; name: string; link?: string | null };
type: { id: string; name: string | null };
@@ -49,7 +50,11 @@ export default function LabelDetailClient({ id, initial, initialTab, initialQ }:
{initial.label.name}
- {initial.label.labeltypeId ?? "?"}
+
+ {initial.label.labeltypeName
+ ? `${initial.label.labeltypeName} (${initial.label.labeltypeId ?? "?"})`
+ : (initial.label.labeltypeId ?? "?")}
+
diff --git a/src/server/repo/zxdb.ts b/src/server/repo/zxdb.ts
index ab2e8c2..6fe6e3a 100644
--- a/src/server/repo/zxdb.ts
+++ b/src/server/repo/zxdb.ts
@@ -8,6 +8,7 @@ import {
searchByAliases,
searchByOrigins,
labels,
+ labeltypes,
authors,
publishers,
languages,
@@ -31,6 +32,7 @@ import {
licensors,
permissions,
permissiontypes,
+ origintypes,
webrefs,
websites,
magazines,
@@ -297,6 +299,14 @@ export interface EntryDetail {
linkSite?: string | null;
comments?: string | null;
}[];
+ origins?: {
+ type: { id: string; name: string | null };
+ libraryTitle: string;
+ publication: string | null;
+ containerId: number | null;
+ issueId: number | null;
+ date: { year: number | null; month: number | null; day: number | null };
+ }[];
// Additional entry fields for richer details
maxPlayers?: number;
availabletypeId?: string | null;
@@ -559,6 +569,17 @@ export async function getEntryById(id: number): Promise
{
linkSite: string | null;
comments: string | null;
}[] = [];
+ let originRows: {
+ libraryTitle: string;
+ origintypeId: string;
+ origintypeName: string | null;
+ containerId: number | string | null;
+ issueId: number | string | null;
+ dateYear: number | string | null;
+ dateMonth: number | string | null;
+ dateDay: number | string | null;
+ publication: string | null;
+ }[] = [];
try {
aliasRows = await db
.select({ releaseSeq: aliases.releaseSeq, languageId: aliases.languageId, title: aliases.title })
@@ -591,6 +612,24 @@ export async function getEntryById(id: number): Promise {
.where(eq(relatedlicenses.entryId, id));
licenseRows = rows as typeof licenseRows;
} catch {}
+ try {
+ const rows = await db
+ .select({
+ libraryTitle: searchByOrigins.libraryTitle,
+ origintypeId: searchByOrigins.origintypeId,
+ origintypeName: origintypes.name,
+ containerId: searchByOrigins.containerId,
+ issueId: searchByOrigins.issueId,
+ dateYear: searchByOrigins.dateYear,
+ dateMonth: searchByOrigins.dateMonth,
+ dateDay: searchByOrigins.dateDay,
+ publication: searchByOrigins.publication,
+ })
+ .from(searchByOrigins)
+ .leftJoin(origintypes, eq(origintypes.id, searchByOrigins.origintypeId))
+ .where(eq(searchByOrigins.entryId, id));
+ originRows = rows as typeof originRows;
+ } catch {}
return {
id: base.id,
@@ -610,6 +649,18 @@ export async function getEntryById(id: number): Promise {
linkSite: l.linkSite ?? null,
comments: l.comments ?? null,
})),
+ origins: originRows.map((o) => ({
+ type: { id: o.origintypeId, name: o.origintypeName ?? null },
+ libraryTitle: o.libraryTitle,
+ publication: o.publication ?? null,
+ containerId: o.containerId != null ? Number(o.containerId) : null,
+ issueId: o.issueId != null ? Number(o.issueId) : null,
+ date: {
+ year: o.dateYear != null ? Number(o.dateYear) : null,
+ month: o.dateMonth != null ? Number(o.dateMonth) : null,
+ day: o.dateDay != null ? Number(o.dateDay) : null,
+ },
+ })),
maxPlayers: (base.maxPlayers) ?? undefined,
availabletypeId: (base.availabletypeId) ?? undefined,
withoutLoadScreen: (base.withoutLoadScreen) ?? undefined,
@@ -651,6 +702,7 @@ export async function getEntryById(id: number): Promise {
// ----- Labels -----
export interface LabelDetail extends LabelSummary {
+ labeltypeName: string | null;
permissions: {
website: { id: number; name: string; link?: string | null };
type: { id: string; name: string | null };
@@ -709,7 +761,17 @@ export async function searchLabels(params: LabelSearchParams): Promise {
- const rows = await db.select().from(labels).where(eq(labels.id, id)).limit(1);
+ const rows = await db
+ .select({
+ id: labels.id,
+ name: labels.name,
+ labeltypeId: labels.labeltypeId,
+ labeltypeName: labeltypes.name,
+ })
+ .from(labels)
+ .leftJoin(labeltypes, eq(labeltypes.id, labels.labeltypeId))
+ .where(eq(labels.id, id))
+ .limit(1);
const base = rows[0];
if (!base) return null;
@@ -770,6 +832,7 @@ export async function getLabelById(id: number): Promise {
id: base.id,
name: base.name,
labeltypeId: base.labeltypeId,
+ labeltypeName: base.labeltypeName ?? null,
permissions: permissionRows.map((p) => ({
website: { id: Number(p.websiteId), name: p.websiteName, link: p.websiteLink ?? null },
type: { id: p.permissiontypeId, name: p.permissiontypeName ?? null },