1
0
Fork 0

feat(voiceover): add description and spoiler fields to voice scripts

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
Jason Fraley 2026-09-07 00:34:32 -04:00
parent eecedece6b
commit 92117374b7
8 changed files with 46535 additions and 2 deletions

View file

@ -6,7 +6,7 @@ export const VoiceScripts: CollectionConfig = {
admin: { admin: {
group: "Voiceover", group: "Voiceover",
useAsTitle: "title", useAsTitle: "title",
defaultColumns: ["title", "xpAmount", "status", "createdAt"], defaultColumns: ["title", "xpAmount", "spoiler", "status", "createdAt"],
}, },
access: { access: {
read: ({ req }) => Boolean(req.user), read: ({ req }) => Boolean(req.user),
@ -20,6 +20,15 @@ export const VoiceScripts: CollectionConfig = {
type: "text", type: "text",
required: true, required: true,
}, },
{
name: "description",
label: "Context Description",
type: "textarea",
admin: {
description:
"Optional context for readers: who is speaking, where this line happens, and anything else they should know before recording.",
},
},
{ {
name: "script", name: "script",
type: "textarea", type: "textarea",
@ -40,6 +49,16 @@ export const VoiceScripts: CollectionConfig = {
description: "XP awarded per accepted submission of this script.", description: "XP awarded per accepted submission of this script.",
}, },
}, },
{
name: "spoiler",
label: "Potential Campaign Spoilers",
type: "checkbox",
defaultValue: false,
admin: {
description:
"Warns readers on the frontend that this script may include, infer, or expose campaign spoilers.",
},
},
{ {
name: "status", name: "status",
type: "select", type: "select",

View file

@ -12,9 +12,11 @@ export interface VoiceoverSubmissionSummary {
export interface VoiceoverScriptView { export interface VoiceoverScriptView {
id: number; id: number;
title: string; title: string;
description: string | null;
script: string; script: string;
xpAmount: number; xpAmount: number;
status: string; status: string;
spoiler: boolean;
createdAt: string; createdAt: string;
/** This user's own submissions on the script, newest first. */ /** This user's own submissions on the script, newest first. */
mySubmissions: VoiceoverSubmissionSummary[]; mySubmissions: VoiceoverSubmissionSummary[];
@ -59,9 +61,11 @@ function buildScriptView(
return { return {
id: script.id, id: script.id,
title: script.title, title: script.title,
description: script.description ?? null,
script: script.script, script: script.script,
xpAmount: script.xpAmount, xpAmount: script.xpAmount,
status: script.status, status: script.status,
spoiler: script.spoiler ?? false,
createdAt: script.createdAt, createdAt: script.createdAt,
mySubmissions, mySubmissions,
otherSubmissionCount, otherSubmissionCount,

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
ALTER TABLE "voice_scripts" ADD COLUMN "spoiler" boolean DEFAULT false;`)
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
ALTER TABLE "voice_scripts" DROP COLUMN "spoiler";`)
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
ALTER TABLE "voice_scripts" ADD COLUMN "description" varchar;`)
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
ALTER TABLE "voice_scripts" DROP COLUMN "description";`)
}

View file

@ -37,6 +37,8 @@ import * as migration_20260906_165837_add_market_state_event_target from './2026
import * as migration_20260906_202925_add_voice_submissions from './20260906_202925_add_voice_submissions'; import * as migration_20260906_202925_add_voice_submissions from './20260906_202925_add_voice_submissions';
import * as migration_20260907_012326_add_missions_created_by from './20260907_012326_add_missions_created_by'; import * as migration_20260907_012326_add_missions_created_by from './20260907_012326_add_missions_created_by';
import * as migration_20260907_013724_make_missions_campaign_optional from './20260907_013724_make_missions_campaign_optional'; import * as migration_20260907_013724_make_missions_campaign_optional from './20260907_013724_make_missions_campaign_optional';
import * as migration_20260907_041051_add_voice_script_spoiler from './20260907_041051_add_voice_script_spoiler';
import * as migration_20260907_043339_add_voice_script_description from './20260907_043339_add_voice_script_description';
export const migrations = [ export const migrations = [
{ {
@ -232,6 +234,16 @@ export const migrations = [
{ {
up: migration_20260907_013724_make_missions_campaign_optional.up, up: migration_20260907_013724_make_missions_campaign_optional.up,
down: migration_20260907_013724_make_missions_campaign_optional.down, down: migration_20260907_013724_make_missions_campaign_optional.down,
name: '20260907_013724_make_missions_campaign_optional' name: '20260907_013724_make_missions_campaign_optional',
},
{
up: migration_20260907_041051_add_voice_script_spoiler.up,
down: migration_20260907_041051_add_voice_script_spoiler.down,
name: '20260907_041051_add_voice_script_spoiler',
},
{
up: migration_20260907_043339_add_voice_script_description.up,
down: migration_20260907_043339_add_voice_script_description.down,
name: '20260907_043339_add_voice_script_description'
}, },
]; ];

View file

@ -3092,6 +3092,10 @@ export interface MarketState {
export interface VoiceScript { export interface VoiceScript {
id: number; id: number;
title: string; title: string;
/**
* Optional context for readers: who is speaking, where this line happens, and anything else they should know before recording.
*/
description?: string | null;
/** /**
* Voice talent reads this verbatim. Inline emotion tags like [calm] are stored as written. * Voice talent reads this verbatim. Inline emotion tags like [calm] are stored as written.
*/ */
@ -3100,6 +3104,10 @@ export interface VoiceScript {
* XP awarded per accepted submission of this script. * XP awarded per accepted submission of this script.
*/ */
xpAmount: number; xpAmount: number;
/**
* Warns readers on the frontend that this script may include, infer, or expose campaign spoilers.
*/
spoiler?: boolean | null;
/** /**
* Closed scripts reject new submissions * Closed scripts reject new submissions
*/ */
@ -5207,8 +5215,10 @@ export interface MarketStateSelect<T extends boolean = true> {
*/ */
export interface VoiceScriptsSelect<T extends boolean = true> { export interface VoiceScriptsSelect<T extends boolean = true> {
title?: T; title?: T;
description?: T;
script?: T; script?: T;
xpAmount?: T; xpAmount?: T;
spoiler?: T;
status?: T; status?: T;
updatedAt?: T; updatedAt?: T;
createdAt?: T; createdAt?: T;