- Create Economist SubmissionTracking package correctly: * mainArticle = full blog post content * coverLetter = 216-word SIR— letter * Links to blog post via blogPostId - Archive 'Letter to The Economist' from blog posts (it's the cover letter) - Fix date display on article cards (use published_at) - Target publication already displaying via blue badge Database changes: - Make blogPostId optional in SubmissionTracking model - Economist package ID: 68fa85ae49d4900e7f2ecd83 - Le Monde package ID: 68fa2abd2e6acd5691932150 Next: Enhanced modal with tabs, validation, export 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
286 lines
13 KiB
HTML
286 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Case Study Moderation | Tractatus Admin</title>
|
|
<link rel="icon" type="image/svg+xml" href="/favicon-new.svg">
|
|
<link rel="stylesheet" href="/css/tailwind.css?v=1761163813">
|
|
<link rel="stylesheet" href="/css/tractatus-theme.min.css?v=1761163813">
|
|
<script src="/js/admin/auth-check.js?v=1761163813"></script>
|
|
</head>
|
|
<body class="bg-gray-50">
|
|
|
|
<!-- Navigation -->
|
|
<nav class="bg-white border-b border-gray-200">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex justify-between h-16">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0 flex items-center">
|
|
<div class="h-8 w-8 bg-blue-600 rounded-lg flex items-center justify-center">
|
|
<svg aria-hidden="true" class="h-5 w-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
|
</svg>
|
|
</div>
|
|
<span class="ml-3 text-xl font-bold text-gray-900">Case Moderation</span>
|
|
</div>
|
|
<div class="ml-10 flex items-baseline space-x-4">
|
|
<a href="/admin/dashboard.html" class="px-3 py-2 rounded-md text-sm font-medium text-gray-600 hover:text-gray-900">Dashboard</a>
|
|
<a href="/admin/blog-curation.html" class="px-3 py-2 rounded-md text-sm font-medium text-gray-600 hover:text-gray-900">Blog</a>
|
|
<a href="/admin/media-triage.html" class="px-3 py-2 rounded-md text-sm font-medium text-gray-600 hover:text-gray-900">Media</a>
|
|
<a href="/admin/case-moderation.html" class="px-3 py-2 rounded-md text-sm font-medium bg-blue-50 text-blue-700">Cases</a>
|
|
<a href="/admin/project-manager.html" class="px-3 py-2 rounded-md text-sm font-medium text-gray-600 hover:text-gray-900">Projects</a>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center">
|
|
<span id="admin-name" class="text-sm text-gray-600 mr-4"></span>
|
|
<button id="logout-btn" class="text-sm font-medium text-gray-700 hover:text-gray-900">
|
|
Logout
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Main Content -->
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
|
|
<!-- Header -->
|
|
<div class="mb-8">
|
|
<h1 class="text-3xl font-bold text-gray-900">Case Study Submissions</h1>
|
|
<p class="mt-1 text-sm text-gray-600">Community-submitted LLM failure mode case studies for review</p>
|
|
</div>
|
|
|
|
<!-- Statistics Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
|
<!-- Total Submissions -->
|
|
<div class="bg-white rounded-lg shadow p-6">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0 bg-blue-100 rounded-md p-3">
|
|
<svg aria-hidden="true" class="h-6 w-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="ml-4">
|
|
<p class="text-sm font-medium text-gray-500">Total</p>
|
|
<p id="stat-total" class="text-2xl font-semibold text-gray-900">-</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pending Review -->
|
|
<div class="bg-white rounded-lg shadow p-6">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0 bg-yellow-100 rounded-md p-3">
|
|
<svg aria-hidden="true" class="h-6 w-6 text-yellow-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="ml-4">
|
|
<p class="text-sm font-medium text-gray-500">Pending</p>
|
|
<p id="stat-pending" class="text-2xl font-semibold text-gray-900">-</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Approved -->
|
|
<div class="bg-white rounded-lg shadow p-6">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0 bg-green-100 rounded-md p-3">
|
|
<svg aria-hidden="true" class="h-6 w-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="ml-4">
|
|
<p class="text-sm font-medium text-gray-500">Approved</p>
|
|
<p id="stat-approved" class="text-2xl font-semibold text-gray-900">-</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Rejected -->
|
|
<div class="bg-white rounded-lg shadow p-6">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0 bg-red-100 rounded-md p-3">
|
|
<svg aria-hidden="true" class="h-6 w-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="ml-4">
|
|
<p class="text-sm font-medium text-gray-500">Rejected</p>
|
|
<p id="stat-rejected" class="text-2xl font-semibold text-gray-900">-</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<div class="bg-white rounded-lg shadow mb-6">
|
|
<div class="px-6 py-4 border-b border-gray-200">
|
|
<h3 class="text-lg font-medium text-gray-900">Filters</h3>
|
|
</div>
|
|
<div class="px-6 py-4">
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
<!-- Status Filter -->
|
|
<div>
|
|
<label for="filter-status" class="block text-sm font-medium text-gray-700 mb-1">Status</label>
|
|
<select id="filter-status" class="w-full text-sm border-gray-300 rounded-md">
|
|
<option value="">All Submissions</option>
|
|
<option value="pending" selected>Pending Review</option>
|
|
<option value="approved">Approved</option>
|
|
<option value="rejected">Rejected</option>
|
|
<option value="needs_info">Needs More Info</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Failure Mode Filter -->
|
|
<div>
|
|
<label for="filter-failure-mode" class="block text-sm font-medium text-gray-700 mb-1">Failure Mode</label>
|
|
<select id="filter-failure-mode" class="w-full text-sm border-gray-300 rounded-md">
|
|
<option value="">All Types</option>
|
|
<option value="pattern_bias">Pattern Bias</option>
|
|
<option value="instruction_override">Instruction Override</option>
|
|
<option value="context_pressure">Context Pressure</option>
|
|
<option value="hallucination">Hallucination</option>
|
|
<option value="boundary_violation">Boundary Violation</option>
|
|
<option value="values_decision">Values Decision</option>
|
|
<option value="other">Other</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- AI Score Filter -->
|
|
<div>
|
|
<label for="filter-score" class="block text-sm font-medium text-gray-700 mb-1">AI Relevance Score</label>
|
|
<select id="filter-score" class="w-full text-sm border-gray-300 rounded-md">
|
|
<option value="">All Scores</option>
|
|
<option value="high">High (≥0.7)</option>
|
|
<option value="medium">Medium (0.4-0.7)</option>
|
|
<option value="low">Low (<0.4)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Sort By -->
|
|
<div>
|
|
<label for="sort-by" class="block text-sm font-medium text-gray-700 mb-1">Sort By</label>
|
|
<select id="sort-by" class="w-full text-sm border-gray-300 rounded-md">
|
|
<option value="submitted_at">Date Submitted</option>
|
|
<option value="relevance_score">Relevance Score</option>
|
|
<option value="completeness_score">Completeness</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4 flex justify-between items-center">
|
|
<button id="clear-filters-btn" class="text-sm text-gray-600 hover:text-gray-900">
|
|
Clear Filters
|
|
</button>
|
|
<span id="filter-results" class="text-sm text-gray-600">
|
|
<!-- Results count will appear here -->
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Submissions List -->
|
|
<div id="submissions-container">
|
|
<!-- Loading State -->
|
|
<div class="bg-white rounded-lg shadow p-12 text-center text-gray-500">
|
|
<div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mb-4"></div>
|
|
<p>Loading case submissions...</p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Submission Details Modal -->
|
|
<div id="details-modal" class="hidden fixed inset-0 bg-gray-500 bg-opacity-75 overflow-y-auto z-50">
|
|
<div class="flex items-center justify-center min-h-screen px-4 py-6">
|
|
<div class="bg-white rounded-lg shadow-xl max-w-5xl w-full max-h-[90vh] overflow-y-auto">
|
|
<!-- Modal Header -->
|
|
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center sticky top-0 bg-white z-10">
|
|
<h3 class="text-xl font-bold text-gray-900">Case Study Submission</h3>
|
|
<button id="close-details-modal" class="text-gray-400 hover:text-gray-600">
|
|
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Modal Content -->
|
|
<div id="details-modal-content" class="px-6 py-4">
|
|
<!-- Content will be populated dynamically -->
|
|
</div>
|
|
|
|
<!-- Modal Footer -->
|
|
<div class="px-6 py-4 border-t border-gray-200 flex justify-end space-x-3 sticky bottom-0 bg-white">
|
|
<button id="details-modal-close-btn" class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200">
|
|
Close
|
|
</button>
|
|
<button id="request-info-btn" class="px-4 py-2 text-sm font-medium text-white bg-yellow-600 rounded-md hover:bg-yellow-700">
|
|
Request More Info
|
|
</button>
|
|
<button id="reject-btn" class="px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-md hover:bg-red-700">
|
|
Reject
|
|
</button>
|
|
<button id="approve-btn" class="px-4 py-2 text-sm font-medium text-white bg-green-600 rounded-md hover:bg-green-700">
|
|
Approve
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Modal (for approve/reject/request info) -->
|
|
<div id="action-modal" class="hidden fixed inset-0 bg-gray-500 bg-opacity-75 overflow-y-auto z-50">
|
|
<div class="flex items-center justify-center min-h-screen px-4 py-6">
|
|
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full">
|
|
<!-- Modal Header -->
|
|
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center">
|
|
<h3 id="action-modal-title" class="text-xl font-bold text-gray-900"></h3>
|
|
<button id="close-action-modal" class="text-gray-400 hover:text-gray-600">
|
|
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Modal Content -->
|
|
<div class="px-6 py-4">
|
|
<div id="action-modal-content">
|
|
<!-- Content will be populated dynamically -->
|
|
</div>
|
|
|
|
<!-- Notes Textarea -->
|
|
<div class="mt-4">
|
|
<label for="action-notes" class="block text-sm font-medium text-gray-700 mb-2">
|
|
<span id="action-notes-label">Notes</span>
|
|
<span class="text-red-600">*</span>
|
|
</label>
|
|
<textarea id="action-notes" rows="6" required
|
|
class="w-full text-sm border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"
|
|
placeholder="Enter your notes..."></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Footer -->
|
|
<div class="px-6 py-4 border-t border-gray-200 flex justify-end space-x-3">
|
|
<button id="action-modal-cancel-btn" class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200">
|
|
Cancel
|
|
</button>
|
|
<button id="action-modal-submit-btn" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700">
|
|
Submit
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toast Notifications -->
|
|
<div id="toast-container" class="fixed top-4 right-4 z-50 space-y-2">
|
|
<!-- Toast messages will appear here -->
|
|
</div>
|
|
|
|
<script src="/js/admin/case-moderation.js?v=1761163813"></script>
|
|
|
|
</body>
|
|
</html>
|