Add viewer-range categories, nomination tracking, dynamic showact form, session timeout, share URLs, and workflow-per-season
Features: - Category viewer ranges + subcategory templates (admin group modal, tree workspace) - Nomination enrichment via TwitchTracker API (NominationEnrichmentService, TwitchTrackerViewerStatsProvider) with admin tracking rules editor - Nomination group tracker: CategoryGroupName as primary identifier, CategoryId stays as nullable legacy field; StreamerIdentity table - Dynamic showact application form builder (AdminShowactFormBuilder, ShowactApplicationSchedule) - Session idle timeout setting (AdminSessionTimeoutCard) - Share URLs for X and Discord (SiteSettings, public extras) - Workflow rules now stored per season (falls back to global SiteSettings) - New admin routes: settings/access, settings/workflows, tracking-rules - New admin review workspace with subcategory tabs - AdminCategoriesView rebuilt with group/subcategory modals Migrations (all additive): - AddShareUrls, AddShowactDynamicForm, AddCategoryViewerRanges, AddSessionIdleTimeoutSettings, AddSeasonSubcategoryTemplates, AddNominationGroupTrackerIdentity, AddShowactApplicationSchedule, AddSeasonWorkflowRulesJson Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+64
-55
@@ -1,6 +1,8 @@
|
||||
namespace Backend.Data;
|
||||
|
||||
internal sealed record CategorySeed(string GroupName, string Name, string Slug, string Description, int SortOrder);
|
||||
using Backend.Services;
|
||||
|
||||
internal sealed record AwardCategorySeed(string LegacyGroupName, string Name, string Slug, string Description, int SortOrder);
|
||||
internal sealed record CandidateSeed(string CategorySlug, string DisplayName, string ChannelSlug, string Platform);
|
||||
internal sealed record WinnerSeed(int Year, string CategorySlug, string DisplayName, string ChannelSlug, string Platform);
|
||||
internal sealed record SiteFaqSeed(string Question, string Answer);
|
||||
@@ -8,10 +10,17 @@ internal sealed record SiteSocialSeed(string Label, string Platform, string Url,
|
||||
|
||||
internal static class SeedCatalog
|
||||
{
|
||||
internal static readonly CategorySeed[] CategorySeeds =
|
||||
internal static readonly SeasonSubcategoryTemplateSetting[] DefaultSubcategoryTemplates =
|
||||
[
|
||||
new("Main Awards", "VTuber des Jahres", "vtuber-des-jahres", "Die groesste Auszeichnung des Jahres.", 1),
|
||||
new("Discovery", "Best Newcomer", "best-newcomer", "Neue Stimmen, neue Welten und frische Energie fuer die Szene.", 2),
|
||||
new("Hidden Star", "hidden-star", 1, 1, 20),
|
||||
new("Rising Star", "rising-star", 2, 21, 60),
|
||||
new("Shining Star", "shining-star", 3, 61, null),
|
||||
];
|
||||
|
||||
internal static readonly AwardCategorySeed[] AwardCategorySeeds =
|
||||
[
|
||||
new("Main Awards", "VTuber des Jahres", "vtuber-des-jahres", "Die größte Auszeichnung des Jahres.", 1),
|
||||
new("Discovery", "Best Newcomer", "best-newcomer", "Neue Stimmen, neue Welten und frische Energie für die Szene.", 2),
|
||||
new("Creative", "Model & Design", "model-design", "Live2D, 3D, Outfit, Rigging und visuelle Identitaet.", 3),
|
||||
new("Performance", "Gesang & Musik", "gesang-musik", "Songs, Covers, Konzerte und musikalische Highlights.", 4),
|
||||
new("Gaming", "Best Gaming", "best-gaming", "Gameplay, Skill, Chaos und legendaere Gaming-Momente.", 5),
|
||||
@@ -34,16 +43,16 @@ internal static class SeedCatalog
|
||||
"Jede:r aktive deutschsprachige VTuber kann nominiert werden — unabhaengig von Follower-Zahl oder Plattform. Die Community schlaegt in der Nominierungsphase ihre Favorit:innen vor."),
|
||||
new(
|
||||
"Wie funktioniert das Voting?",
|
||||
"Du meldest dich ausschliesslich mit deinem Twitch-Account an — nur so kannst du teilnehmen. Das haelt das Voting fair und bot-frei. Danach vergibst du pro Kategorie eine Stimme, aenderbar bis zum Ende der Phase."),
|
||||
"Du meldest dich ausschließlich mit deinem Twitch-Account an — nur so kannst du teilnehmen. Das hält das Voting fair und bot-frei. Danach vergibst du pro Kategorie eine Stimme, änderbar bis zum Ende der Phase."),
|
||||
new(
|
||||
"Was kostet die Teilnahme?",
|
||||
"Gar nichts. Nominieren, voten und die Show schauen ist komplett kostenlos — der VTuber Star Award ist ein Community-Event von Fans fuer Fans."),
|
||||
"Gar nichts. Nominieren, voten und die Show schauen ist komplett kostenlos — der VTuber Star Award ist ein Community-Event von Fans für Fans."),
|
||||
new(
|
||||
"Wann und wo findet die Award-Show statt?",
|
||||
"Die grosse Live-Show wird von Jayuhime gehostet und auf Twitch & YouTube gestreamt. Den genauen Termin findest du im Countdown oben — sei live dabei, wenn die Stars gekuert werden!"),
|
||||
"Die große Live-Show wird von Jayuhime gehostet und auf Twitch & YouTube gestreamt. Den genauen Termin findest du im Countdown oben — sei live dabei, wenn die Stars gekürt werden!"),
|
||||
new(
|
||||
"Ich wurde nominiert — was nun?",
|
||||
"Glueckwunsch! Du erhaeltst eine Benachrichtigung mit allen Infos. Teile deine Nominierung gern mit deiner Community und ruf zum Voten auf — jede Stimme zaehlt."),
|
||||
"Glückwunsch! Du erhältst eine Benachrichtigung mit allen Infos. Teile deine Nominierung gern mit deiner Community und ruf zum Voten auf — jede Stimme zählt."),
|
||||
];
|
||||
|
||||
internal static readonly SiteSocialSeed[] SiteSocialSeeds =
|
||||
@@ -60,18 +69,18 @@ Anbieter
|
||||
VTuber Star Awards, vertreten durch Jayuhime.
|
||||
|
||||
Kontakt
|
||||
Nutze fuer organisatorische Fragen bitte die Kontaktseite oder die hinterlegte Kontaktadresse.
|
||||
Nutze für organisatorische Fragen bitte die Kontaktseite oder die hinterlegte Kontaktadresse.
|
||||
|
||||
Hinweis
|
||||
Dieses Impressum ist ein redaktioneller Platzhalter und sollte vor dem Livegang mit den tatsaechlichen Anbieterangaben ersetzt werden.
|
||||
Dieses Impressum ist ein redaktioneller Platzhalter und sollte vor dem Livegang mit den tatsächlichen Anbieterangaben ersetzt werden.
|
||||
""";
|
||||
|
||||
internal const string DefaultContactContent = """
|
||||
Kontakt zum Award-Team
|
||||
Du hast Fragen zur Nominierung, zum Voting, zu Clips oder zur Show? Schreib dem Team ueber die hinterlegte Kontaktseite.
|
||||
Du hast Fragen zur Nominierung, zum Voting, zu Clips oder zur Show? Schreib dem Team über die hinterlegte Kontaktseite.
|
||||
|
||||
Datenschutzfragen
|
||||
Fuer Datenschutzanfragen nutze bitte die Datenschutz-E-Mail aus diesem Footer.
|
||||
Für Datenschutzanfragen nutze bitte die Datenschutz-E-Mail aus diesem Footer.
|
||||
|
||||
Community & Kooperationen
|
||||
Social Links und Partneranfragen werden vom Admin-Team gepflegt und koordiniert.
|
||||
@@ -79,57 +88,57 @@ Social Links und Partneranfragen werden vom Admin-Team gepflegt und koordiniert.
|
||||
|
||||
internal const string DefaultSponsorsContent = """
|
||||
Sponsoren & Partner
|
||||
Hier koennen Sponsor:innen, Medienpartner, Community-Partner und Supporter des VTuber Star Awards vorgestellt werden.
|
||||
Hier können Sponsor:innen, Medienpartner, Community-Partner und Supporter des VTuber Star Awards vorgestellt werden.
|
||||
|
||||
Partner werden im Rahmen der Show und auf den oeffentlichen Kontaktflaechen genannt, sobald sie final bestaetigt sind.
|
||||
Partner werden im Rahmen der Show und auf den öffentlichen Kontaktflächen genannt, sobald sie final bestätigt sind.
|
||||
""";
|
||||
|
||||
internal static readonly CandidateSeed[] CurrentCandidateSeeds =
|
||||
[
|
||||
new("vtuber-des-jahres", "Hoshimi Miyu", "@hoshimimiyu", "Twitch"),
|
||||
new("vtuber-des-jahres", "Kurainu", "@kurainu", "Twitch"),
|
||||
new("vtuber-des-jahres", "Shiro Ch.", "@shiroch", "Twitch"),
|
||||
new("best-newcomer", "Aoi Sakura", "@aoisakura", "YouTube"),
|
||||
new("best-newcomer", "Nox Live", "@noxlive", "Twitch"),
|
||||
new("model-design", "Velvet Rei", "@velvetrei", "Twitch"),
|
||||
new("model-design", "Mochi Atelier", "@mochiatelier", "Cake"),
|
||||
new("gesang-musik", "Melo Diva", "@melodiva", "YouTube"),
|
||||
new("gesang-musik", "Yuki Stern", "@yukistern", "Twitch"),
|
||||
new("best-gaming", "Kurainu", "@kurainu", "Twitch"),
|
||||
new("best-gaming", "PixelPunk", "@pixelpunk", "Twitch"),
|
||||
new("best-variety", "Taro Chaos", "@tarochaos", "Twitch"),
|
||||
new("best-variety", "Kotaro Plays", "@kotaroplays", "YouTube"),
|
||||
new("community-liebling", "Shiro Ch.", "@shiroch", "Twitch"),
|
||||
new("community-liebling", "Lumi", "@lumi_vt", "Cake"),
|
||||
new("best-collab-duo", "Akari & Nox", "@akari_vt", "Twitch"),
|
||||
new("best-collab-duo", "Mochi & Hana", "@mochi_mochi", "YouTube"),
|
||||
new("vtuber-des-jahres-shining-star", "Hoshimi Miyu", "@hoshimimiyu", "Twitch"),
|
||||
new("vtuber-des-jahres-shining-star", "Kurainu", "@kurainu", "Twitch"),
|
||||
new("vtuber-des-jahres-shining-star", "Shiro Ch.", "@shiroch", "Twitch"),
|
||||
new("best-newcomer-hidden-star", "Aoi Sakura", "@aoisakura", "YouTube"),
|
||||
new("best-newcomer-rising-star", "Nox Live", "@noxlive", "Twitch"),
|
||||
new("model-design-shining-star", "Velvet Rei", "@velvetrei", "Twitch"),
|
||||
new("model-design-rising-star", "Mochi Atelier", "@mochiatelier", "Cake"),
|
||||
new("gesang-musik-shining-star", "Melo Diva", "@melodiva", "YouTube"),
|
||||
new("gesang-musik-rising-star", "Yuki Stern", "@yukistern", "Twitch"),
|
||||
new("best-gaming-shining-star", "Kurainu", "@kurainu", "Twitch"),
|
||||
new("best-gaming-rising-star", "PixelPunk", "@pixelpunk", "Twitch"),
|
||||
new("best-variety-shining-star", "Taro Chaos", "@tarochaos", "Twitch"),
|
||||
new("best-variety-rising-star", "Kotaro Plays", "@kotaroplays", "YouTube"),
|
||||
new("community-liebling-shining-star", "Shiro Ch.", "@shiroch", "Twitch"),
|
||||
new("community-liebling-hidden-star", "Lumi", "@lumi_vt", "Cake"),
|
||||
new("best-collab-duo-shining-star", "Akari & Nox", "@akari_vt", "Twitch"),
|
||||
new("best-collab-duo-rising-star", "Mochi & Hana", "@mochi_mochi", "YouTube"),
|
||||
];
|
||||
|
||||
internal static readonly WinnerSeed[] WinnerSeeds =
|
||||
[
|
||||
new(2025, "vtuber-des-jahres", "Hoshimi Miyu", "@hoshimimiyu", "Twitch"),
|
||||
new(2025, "best-newcomer", "Aoi Sakura", "@aoisakura", "YouTube"),
|
||||
new(2025, "model-design", "Velvet Rei", "@velvetrei", "Twitch"),
|
||||
new(2025, "gesang-musik", "Melo Diva", "@melodiva", "YouTube"),
|
||||
new(2025, "best-gaming", "Kurainu", "@kurainu", "Twitch"),
|
||||
new(2025, "best-variety", "Taro Chaos", "@tarochaos", "Twitch"),
|
||||
new(2025, "community-liebling", "Shiro Ch.", "@shiroch", "Twitch"),
|
||||
new(2025, "best-collab-duo", "Akari & Nox", "@akari_vt", "Cake"),
|
||||
new(2024, "vtuber-des-jahres", "Aoi Sakura", "@aoisakura", "YouTube"),
|
||||
new(2024, "best-newcomer", "Lumi", "@lumi_vt", "Cake"),
|
||||
new(2024, "model-design", "Mochi Atelier", "@mochiatelier", "Cake"),
|
||||
new(2024, "gesang-musik", "Yuki Stern", "@yukistern", "Twitch"),
|
||||
new(2024, "best-gaming", "Starbyte", "@starbyte", "Twitch"),
|
||||
new(2024, "best-variety", "Kotaro Plays", "@kotaroplays", "YouTube"),
|
||||
new(2024, "community-liebling", "Moonrelay", "@moonrelay", "Twitch"),
|
||||
new(2024, "best-collab-duo", "Pixel & Kotaro", "@pixelpunk", "Twitch"),
|
||||
new(2023, "vtuber-des-jahres", "Akari Nova", "@akarinova", "Twitch"),
|
||||
new(2023, "best-newcomer", "Nox Live", "@noxlive", "Twitch"),
|
||||
new(2023, "model-design", "Rei Velvet", "@reivelvet", "YouTube"),
|
||||
new(2023, "gesang-musik", "Tenshi Vox", "@tenshivox", "Twitch"),
|
||||
new(2023, "best-gaming", "Bit Knight", "@bitknight", "Twitch"),
|
||||
new(2023, "best-variety", "Hana Hearts", "@hanahearts", "Cake"),
|
||||
new(2023, "community-liebling", "Sora Blau", "@sorablau", "YouTube"),
|
||||
new(2023, "best-collab-duo", "Yuki & Melo", "@yukistern", "Twitch"),
|
||||
new(2025, "vtuber-des-jahres-shining-star", "Hoshimi Miyu", "@hoshimimiyu", "Twitch"),
|
||||
new(2025, "best-newcomer-hidden-star", "Aoi Sakura", "@aoisakura", "YouTube"),
|
||||
new(2025, "model-design-shining-star", "Velvet Rei", "@velvetrei", "Twitch"),
|
||||
new(2025, "gesang-musik-shining-star", "Melo Diva", "@melodiva", "YouTube"),
|
||||
new(2025, "best-gaming-shining-star", "Kurainu", "@kurainu", "Twitch"),
|
||||
new(2025, "best-variety-shining-star", "Taro Chaos", "@tarochaos", "Twitch"),
|
||||
new(2025, "community-liebling-shining-star", "Shiro Ch.", "@shiroch", "Twitch"),
|
||||
new(2025, "best-collab-duo-shining-star", "Akari & Nox", "@akari_vt", "Cake"),
|
||||
new(2024, "vtuber-des-jahres-shining-star", "Aoi Sakura", "@aoisakura", "YouTube"),
|
||||
new(2024, "best-newcomer-hidden-star", "Lumi", "@lumi_vt", "Cake"),
|
||||
new(2024, "model-design-rising-star", "Mochi Atelier", "@mochiatelier", "Cake"),
|
||||
new(2024, "gesang-musik-rising-star", "Yuki Stern", "@yukistern", "Twitch"),
|
||||
new(2024, "best-gaming-shining-star", "Starbyte", "@starbyte", "Twitch"),
|
||||
new(2024, "best-variety-rising-star", "Kotaro Plays", "@kotaroplays", "YouTube"),
|
||||
new(2024, "community-liebling-rising-star", "Moonrelay", "@moonrelay", "Twitch"),
|
||||
new(2024, "best-collab-duo-rising-star", "Pixel & Kotaro", "@pixelpunk", "Twitch"),
|
||||
new(2023, "vtuber-des-jahres-shining-star", "Akari Nova", "@akarinova", "Twitch"),
|
||||
new(2023, "best-newcomer-rising-star", "Nox Live", "@noxlive", "Twitch"),
|
||||
new(2023, "model-design-shining-star", "Rei Velvet", "@reivelvet", "YouTube"),
|
||||
new(2023, "gesang-musik-shining-star", "Tenshi Vox", "@tenshivox", "Twitch"),
|
||||
new(2023, "best-gaming-rising-star", "Bit Knight", "@bitknight", "Twitch"),
|
||||
new(2023, "best-variety-hidden-star", "Hana Hearts", "@hanahearts", "Cake"),
|
||||
new(2023, "community-liebling-rising-star", "Sora Blau", "@sorablau", "YouTube"),
|
||||
new(2023, "best-collab-duo-rising-star", "Yuki & Melo", "@yukistern", "Twitch"),
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user