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:
@@ -14,15 +14,19 @@ import type {
|
||||
AdminSiteSettingsResponse,
|
||||
AdminSponsorItem,
|
||||
AdminTeamResponse,
|
||||
AdminTrackingRulesResponse,
|
||||
AdminWorkflowRulesResponse,
|
||||
ApproveNominationPayload,
|
||||
AddNominationLinkBlacklistEntryPayload,
|
||||
BulkResolveRiskFlagsPayload,
|
||||
CreateTeamMemberPayload,
|
||||
CreateSeasonPayload,
|
||||
ReopenRejectedNominationPayload,
|
||||
RejectNominationPayload,
|
||||
ResolveRiskFlagPayload,
|
||||
SetAwardResultPayload,
|
||||
UpdateNominationTrackingReviewPayload,
|
||||
UpdateSeasonSubcategoryTemplatesPayload,
|
||||
TeamMemberPasswordResponse,
|
||||
UpdateClipStatusPayload,
|
||||
UpdateOptionalFeatureSettingsPayload,
|
||||
@@ -32,11 +36,15 @@ import type {
|
||||
UpdateNominationLinkBlacklistPayload,
|
||||
UpdateSeasonPayload,
|
||||
UpdateSiteSettingsPayload,
|
||||
UpdateTrackingReviewNotesPayload,
|
||||
UpdateTrackingRulesPayload,
|
||||
UpdateTrackingSourcePayload,
|
||||
UpdateTeamMemberPayload,
|
||||
UpdateTeamRolesPayload,
|
||||
UpdateWorkflowRulesPayload,
|
||||
UpsertCandidatePayload,
|
||||
UpsertCategoryPayload,
|
||||
UpsertCategoryGroupPayload,
|
||||
UpsertSponsorPayload,
|
||||
} from '../../types/awards'
|
||||
import { requestJson } from '../http'
|
||||
@@ -93,9 +101,16 @@ export const adminApi = {
|
||||
getAdminRiskRules: () => requestJson<AdminRiskRulesResponse>('/api/admin/risk-rules'),
|
||||
updateAdminRiskRules: (payload: UpdateRiskRulesPayload) =>
|
||||
requestJson<AdminRiskRulesResponse>('/api/admin/risk-rules', jsonRequest('PUT', payload)),
|
||||
getAdminWorkflowRules: () => requestJson<AdminWorkflowRulesResponse>('/api/admin/workflow-rules'),
|
||||
updateAdminWorkflowRules: (payload: UpdateWorkflowRulesPayload) =>
|
||||
requestJson<AdminWorkflowRulesResponse>('/api/admin/workflow-rules', jsonRequest('PUT', payload)),
|
||||
getAdminWorkflowRules: (seasonId: number) => requestJson<AdminWorkflowRulesResponse>(`/api/admin/seasons/${seasonId}/workflow-rules`),
|
||||
updateAdminWorkflowRules: (seasonId: number, payload: UpdateWorkflowRulesPayload) =>
|
||||
requestJson<AdminWorkflowRulesResponse>(`/api/admin/seasons/${seasonId}/workflow-rules`, jsonRequest('PUT', payload)),
|
||||
getAdminTrackingRules: () => requestJson<AdminTrackingRulesResponse>('/api/admin/tracking-rules'),
|
||||
updateAdminTrackingRules: (payload: UpdateTrackingRulesPayload) =>
|
||||
requestJson<AdminTrackingRulesResponse>('/api/admin/tracking-rules', jsonRequest('PUT', payload)),
|
||||
updateAdminTrackingSource: (payload: UpdateTrackingSourcePayload) =>
|
||||
requestJson<AdminTrackingRulesResponse>('/api/admin/tracking-rules/source', jsonRequest('PUT', payload)),
|
||||
updateAdminTrackingReviewNotes: (payload: UpdateTrackingReviewNotesPayload) =>
|
||||
requestJson<AdminTrackingRulesResponse>('/api/admin/tracking-rules/notes', jsonRequest('PUT', payload)),
|
||||
getAdminSeasons: () => requestJson<AdminSeasonListItem[]>('/api/admin/seasons'),
|
||||
getAdminSeasonDetail: (seasonId: number) =>
|
||||
requestJson<AdminSeasonDetailResponse>(`/api/admin/seasons/${seasonId}`),
|
||||
@@ -157,6 +172,26 @@ export const adminApi = {
|
||||
requestJson<{ deleted: boolean; categoryId: number }>(`/api/admin/categories/${categoryId}`, {
|
||||
method: 'DELETE',
|
||||
}),
|
||||
updateAdminSeasonSubcategoryTemplates: (seasonId: number, payload: UpdateSeasonSubcategoryTemplatesPayload) =>
|
||||
requestJson<{ saved: boolean; seasonId: number; templateCount: number }>(
|
||||
`/api/admin/seasons/${seasonId}/subcategory-templates`,
|
||||
jsonRequest('PUT', payload),
|
||||
),
|
||||
createAdminCategoryGroup: (seasonId: number, payload: UpsertCategoryGroupPayload) =>
|
||||
requestJson<{ saved: boolean; seasonId: number; groupName: string }>(
|
||||
`/api/admin/seasons/${seasonId}/category-groups`,
|
||||
jsonRequest('POST', payload),
|
||||
),
|
||||
updateAdminCategoryGroup: (seasonId: number, groupName: string, payload: UpsertCategoryGroupPayload) =>
|
||||
requestJson<{ saved: boolean; seasonId: number; groupName: string }>(
|
||||
`/api/admin/seasons/${seasonId}/category-groups/${encodeURIComponent(groupName)}`,
|
||||
jsonRequest('PUT', payload),
|
||||
),
|
||||
deleteAdminCategoryGroup: (seasonId: number, groupName: string) =>
|
||||
requestJson<{ deleted: boolean; seasonId: number; groupName: string }>(
|
||||
`/api/admin/seasons/${seasonId}/category-groups/${encodeURIComponent(groupName)}`,
|
||||
{ method: 'DELETE' },
|
||||
),
|
||||
createAdminCandidate: (seasonId: number, payload: UpsertCandidatePayload) =>
|
||||
requestJson<{ saved: boolean; candidateId: number }>(`/api/admin/seasons/${seasonId}/candidates`, jsonRequest('POST', payload)),
|
||||
updateAdminCandidate: (candidateId: number, payload: UpsertCandidatePayload) =>
|
||||
@@ -190,6 +225,16 @@ export const adminApi = {
|
||||
`/api/admin/nominations/${nominationId}/reject`,
|
||||
jsonRequest('POST', payload),
|
||||
),
|
||||
reopenRejectedAdminNomination: (nominationId: number, payload: ReopenRejectedNominationPayload = {}) =>
|
||||
requestJson<{ saved: boolean; nominationId: number; reopened: boolean }>(
|
||||
`/api/admin/nominations/${nominationId}/reopen`,
|
||||
jsonRequest('POST', payload),
|
||||
),
|
||||
updateNominationTrackingReview: (nominationId: number, payload: UpdateNominationTrackingReviewPayload) =>
|
||||
requestJson<{ saved: boolean; nominationId: number; status: string }>(
|
||||
`/api/admin/nominations/${nominationId}/tracking-review`,
|
||||
jsonRequest('POST', payload),
|
||||
),
|
||||
getAdminNominationLinkBlacklist: () =>
|
||||
requestJson<AdminNominationLinkBlacklistResponse>('/api/admin/nominations/link-blacklist'),
|
||||
updateAdminNominationLinkBlacklist: (payload: UpdateNominationLinkBlacklistPayload) =>
|
||||
|
||||
Reference in New Issue
Block a user