Add structured moderation assessments with revision history

This commit is contained in:
2026-10-17 19:47:28 -04:00
parent aca728b557
commit 428aefdf24
18 changed files with 1182 additions and 2 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ export const GET: RequestHandler = ({ locals, url }) => {
export const POST: RequestHandler = async ({ locals, request }) => {
try {
const actor = requireUser(locals.user);
const body = await authBody(request, 16 * 1024);
const body = await authBody(request, 64 * 1024);
if (body.op === 'configure')
return json(
moderationMutation(actor.id, body, () =>
+26
View File
@@ -7,6 +7,8 @@
canRevokeModerationRestriction,
moderationCaseStatuses,
moderationCaseStatusLabels,
moderationConcernLabels,
moderationFindingLabels,
type ModerationOverview,
type ModerationQuery,
type ModerationGame
@@ -29,6 +31,7 @@
import Button from '$ui/components/primitives/Button.svelte';
import Tabs from '$ui/components/primitives/Tabs.svelte';
import StatusBadge from '$ui/components/primitives/StatusBadge.svelte';
import Badge from '$ui/components/primitives/Badge.svelte';
import EmptyState from '$ui/components/primitives/EmptyState.svelte';
import RelativeTime from '$ui/components/RelativeTime.svelte';
import Freshness from '$ui/components/Freshness.svelte';
@@ -609,6 +612,22 @@
>
· {moderationGameName(item.game)}
</p>
{#if item.assessment}
<p class="assessment-summary">{item.assessment.summary}</p>
<div class="record-heading" aria-label="Assessment findings">
{#each item.assessment.findings as finding}
<Badge
variant={finding.finding === 'substantiated'
? 'warning'
: 'neutral'}
>
{moderationConcernLabels[finding.category]} · {moderationFindingLabels[
finding.finding
]}
</Badge>
{/each}
</div>
{:else}<p class="hint">Not assessed</p>{/if}
<dl>
<div>
<dt>Priority</dt>
@@ -874,4 +893,11 @@
flex: 1 1 100%;
}
}
.assessment-summary {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
line-clamp: 3;
overflow: hidden;
}
</style>
@@ -31,6 +31,7 @@
import ModerationDialog from '$ui/components/moderation/ModerationDialog.svelte';
import EvidenceMessages from '$ui/components/moderation/EvidenceMessages.svelte';
import LinkCaseActionDialog from '$ui/components/moderation/LinkCaseActionDialog.svelte';
import CaseAssessment from '$ui/components/moderation/CaseAssessment.svelte';
import { preservedConversation } from '$ui/moderation-evidence.js';
let { data }: { data: { moderationCase: ModerationCaseDetail } } = $props();
@@ -159,6 +160,11 @@
cancelRefresh();
void refresh();
}
function assessmentSaved() {
notice = 'Case assessment saved. The earlier assessment remains in revision history.';
cancelRefresh();
void refresh();
}
function archiveContext(raw: string | null | undefined) {
if (!raw) return null;
@@ -273,6 +279,14 @@
<div class="workspace">
<div class="case-main">
<CaseAssessment
caseId={item.id}
revision={item.revision}
assessment={report.assessment}
history={report.assessmentHistory}
{permitted}
onsubmitted={assessmentSaved}
/>
<section class="panel" aria-labelledby="evidence-title">
<div class="section-heading">
<h2 id="evidence-title">