Add winner archive, host image upload and live demo data
Deliver the demo-ready feature set and seed data so the live site can be presented end to end: - Winner archive: ArchivedWinner domain, admin CRUD endpoints/view/manager and public archive surface, backed by AddArchivedWinners migration. - Host presentation: host image upload and artist name on SiteSettings with public image endpoint and supporting migrations. - Clip submissions: idempotent table-ensure migration plus current-season demo clips for review workflows. - Demo seed data: sponsors, share links and 2025 archived winners, with a guarded RemoveDemoSeasons cleanup; all seeds guard against real data. - EnsureRuntimeSchemaParity migration to align runtime schema defensively. - Admin/home UI refinements; remove unused team role permissions modal and dead share-quick-links code. All seed and schema migrations are idempotent (IF NOT EXISTS / ON CONFLICT) and skip when real season data is present. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
using Backend.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Backend.Migrations;
|
||||
|
||||
[DbContext(typeof(AwardsDbContext))]
|
||||
[Migration("20260629213000_EnsureClipSubmissionsTable")]
|
||||
public partial class EnsureClipSubmissionsTable : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS "ClipSubmissions" (
|
||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
|
||||
"SeasonId" integer NOT NULL,
|
||||
"CategoryId" integer,
|
||||
"CandidateId" integer,
|
||||
"SubmittedByTwitchId" character varying(120) NOT NULL,
|
||||
"ClipUrl" character varying(500) NOT NULL,
|
||||
"Title" character varying(200) NOT NULL,
|
||||
"Creator" character varying(120) NOT NULL,
|
||||
"Platform" character varying(40) NOT NULL,
|
||||
"Status" character varying(20) NOT NULL,
|
||||
"ReviewNote" character varying(500),
|
||||
"ReviewedByTwitchId" character varying(120),
|
||||
"CreatedFromIp" character varying(80) NOT NULL,
|
||||
"CreatedAt" timestamp with time zone NOT NULL,
|
||||
"ReviewedAt" timestamp with time zone,
|
||||
CONSTRAINT "PK_ClipSubmissions" PRIMARY KEY ("Id")
|
||||
);
|
||||
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "SeasonId" integer NOT NULL DEFAULT 0;
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "CategoryId" integer;
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "CandidateId" integer;
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "SubmittedByTwitchId" character varying(120) NOT NULL DEFAULT '';
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "ClipUrl" character varying(500) NOT NULL DEFAULT '';
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "Title" character varying(200) NOT NULL DEFAULT '';
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "Creator" character varying(120) NOT NULL DEFAULT '';
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "Platform" character varying(40) NOT NULL DEFAULT '';
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "Status" character varying(20) NOT NULL DEFAULT 'pending';
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "ReviewNote" character varying(500);
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "ReviewedByTwitchId" character varying(120);
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "CreatedFromIp" character varying(80) NOT NULL DEFAULT '';
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "CreatedAt" timestamp with time zone NOT NULL DEFAULT NOW();
|
||||
ALTER TABLE "ClipSubmissions" ADD COLUMN IF NOT EXISTS "ReviewedAt" timestamp with time zone;
|
||||
|
||||
DO $vtsa_clip_constraints$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'FK_ClipSubmissions_Seasons_SeasonId'
|
||||
) THEN
|
||||
ALTER TABLE "ClipSubmissions"
|
||||
ADD CONSTRAINT "FK_ClipSubmissions_Seasons_SeasonId"
|
||||
FOREIGN KEY ("SeasonId") REFERENCES "Seasons"("Id") ON DELETE CASCADE;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'FK_ClipSubmissions_Candidates_CandidateId'
|
||||
) THEN
|
||||
ALTER TABLE "ClipSubmissions"
|
||||
ADD CONSTRAINT "FK_ClipSubmissions_Candidates_CandidateId"
|
||||
FOREIGN KEY ("CandidateId") REFERENCES "Candidates"("Id") ON DELETE SET NULL;
|
||||
END IF;
|
||||
END;
|
||||
$vtsa_clip_constraints$;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_ClipSubmissions_CandidateId"
|
||||
ON "ClipSubmissions" ("CandidateId");
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_ClipSubmissions_SeasonId_Status"
|
||||
ON "ClipSubmissions" ("SeasonId", "Status");
|
||||
|
||||
DO $vtsa_clip_seed$
|
||||
DECLARE
|
||||
target_season_id integer;
|
||||
BEGIN
|
||||
SELECT "Id"
|
||||
INTO target_season_id
|
||||
FROM "Seasons"
|
||||
WHERE "IsCurrent" = TRUE
|
||||
ORDER BY "Year" DESC
|
||||
LIMIT 1;
|
||||
|
||||
IF target_season_id IS NULL THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM "ClipSubmissions"
|
||||
WHERE "SeasonId" = target_season_id
|
||||
) THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
INSERT INTO "ClipSubmissions" (
|
||||
"SeasonId",
|
||||
"CategoryId",
|
||||
"CandidateId",
|
||||
"SubmittedByTwitchId",
|
||||
"ClipUrl",
|
||||
"Title",
|
||||
"Creator",
|
||||
"Platform",
|
||||
"Status",
|
||||
"ReviewNote",
|
||||
"ReviewedByTwitchId",
|
||||
"CreatedFromIp",
|
||||
"CreatedAt",
|
||||
"ReviewedAt"
|
||||
)
|
||||
SELECT
|
||||
target_season_id,
|
||||
candidates."CategoryId",
|
||||
candidates."Id",
|
||||
seed_rows.submitted_by,
|
||||
seed_rows.clip_url,
|
||||
seed_rows.title,
|
||||
seed_rows.creator,
|
||||
seed_rows.platform,
|
||||
seed_rows.status,
|
||||
seed_rows.review_note,
|
||||
seed_rows.reviewed_by,
|
||||
'127.0.0.1',
|
||||
seed_rows.created_at,
|
||||
seed_rows.reviewed_at
|
||||
FROM (
|
||||
VALUES
|
||||
('vtsa_demo_current_astra_shining_star_aster', 'viewer_2001', 'https://clips.twitch.tv/demo-nova-finale', 'Astra turns the boss fight', 'viewer_2001', 'Twitch', 'approved', 'Kontext passt.', 'clip_reviewer', TIMESTAMPTZ '2026-06-20 18:12:00+00', TIMESTAMPTZ '2026-06-21 09:00:00+00'),
|
||||
('vtsa_demo_current_melo_rising_star_aster', 'viewer_2002', 'https://youtu.be/demo-vera-stage', 'Melo sings the finale bridge', 'viewer_2002', 'YouTube', 'approved', NULL, 'clip_reviewer', TIMESTAMPTZ '2026-06-20 20:25:00+00', TIMESTAMPTZ '2026-06-21 09:08:00+00'),
|
||||
('vtsa_demo_current_lumi_shining_star_aster', 'viewer_2003', 'https://clips.twitch.tv/demo-ember-moment', 'Lumi opens the community event', 'viewer_2003', 'Twitch', 'pending', 'Timing pruefen.', NULL, TIMESTAMPTZ '2026-06-21 11:40:00+00', NULL),
|
||||
('vtsa_demo_current_velvet_shining_star_aster', 'viewer_2004', 'https://youtu.be/demo-chroma-design', 'Velvet explains the overlay rebuild', 'viewer_2004', 'YouTube', 'approved', NULL, 'clip_reviewer', TIMESTAMPTZ '2026-06-21 15:10:00+00', TIMESTAMPTZ '2026-06-22 08:45:00+00'),
|
||||
('vtsa_demo_current_lumi_rising_star_aster', 'viewer_2005', 'https://clips.twitch.tv/demo-sora-community', 'Lumi lets chat design the scene', 'viewer_2005', 'Twitch', 'pending', NULL, NULL, TIMESTAMPTZ '2026-06-22 19:55:00+00', NULL)
|
||||
) AS seed_rows(
|
||||
channel_slug,
|
||||
submitted_by,
|
||||
clip_url,
|
||||
title,
|
||||
creator,
|
||||
platform,
|
||||
status,
|
||||
review_note,
|
||||
reviewed_by,
|
||||
created_at,
|
||||
reviewed_at
|
||||
)
|
||||
INNER JOIN "Candidates" candidates
|
||||
ON candidates."SeasonId" = target_season_id
|
||||
AND lower(candidates."ChannelSlug") = lower(seed_rows.channel_slug);
|
||||
|
||||
PERFORM setval(
|
||||
pg_get_serial_sequence('"ClipSubmissions"', 'Id'),
|
||||
COALESCE((SELECT MAX("Id") FROM "ClipSubmissions"), 1)
|
||||
);
|
||||
END;
|
||||
$vtsa_clip_seed$;
|
||||
"""
|
||||
);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
DELETE FROM "ClipSubmissions"
|
||||
WHERE "SubmittedByTwitchId" IN ('viewer_2001', 'viewer_2002', 'viewer_2003', 'viewer_2004', 'viewer_2005');
|
||||
"""
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user