tractatus/public/admin/blog-curation.html.backup
TheFlow 2298d36bed fix(submissions): restructure Economist package and fix article display
- 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>
2025-10-24 08:47:42 +13:00

421 lines
23 KiB
Text

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>External Communications Manager | Tractatus Admin</title>
<link rel="stylesheet" href="/css/tailwind.css?v=1761220417">
<link rel="stylesheet" href="/css/tractatus-theme.min.css?v=1761220417">
<script defer src="/js/admin/auth-check.js?v=1761220417"></script>
<style>
.content-type-card input[type="radio"]:checked + div {
border-color: #3b82f6;
background-color: #eff6ff;
}
</style>
</head>
<body class="bg-gray-50">
<!-- Navigation -->
<div id="admin-navbar" data-page-title="External Communications" data-page-icon="blog"></div>
<script src="/js/components/navbar-admin.js?v=1761220417"></script>
<!-- Main Content -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Section Navigation Tabs -->
<div class="mb-6">
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-8" aria-label="Tabs">
<button data-section="validation" class="section-tab border-blue-500 text-blue-600 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
📋 Pre-Submission
</button>
<button data-section="draft" class="section-tab border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
✨ Generate
</button>
<button data-section="queue" class="section-tab border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
⏳ AI Draft Approval
</button>
<button data-section="guidelines" class="section-tab border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
📖 Guidelines
</button>
<button data-section="published" class="section-tab border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
📰 Published
</button>
</nav>
</div>
<div class="mt-2 text-xs text-gray-500 px-1">
<strong>Workflow:</strong> Generate → AI Approval → Pre-Submission (validate & prep) → Submit to publications
</div>
</div>
<!-- Tractatus Enforcement Notice -->
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<div class="flex">
<div class="flex-shrink-0">
<svg aria-hidden="true" class="h-5 w-5 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/>
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800">Tractatus Framework Enforcement Active</h3>
<div class="mt-2 text-sm text-blue-700">
<p>All AI-generated content is validated against:</p>
<ul class="list-disc list-inside mt-1 space-y-1">
<li><strong>inst_016:</strong> No fabricated statistics or unverifiable claims</li>
<li><strong>inst_017:</strong> No absolute assurance terms (guarantee, 100%, etc.)</li>
<li><strong>inst_018:</strong> No unverified production-ready claims</li>
</ul>
<p class="mt-2 text-xs">🤖 <strong>TRA-OPS-0002:</strong> AI suggests, human decides. All content requires human review and approval.</p>
</div>
</div>
</div>
</div>
<!-- Draft Content Section -->
<div id="draft-section" class="hidden">
<h2 class="text-2xl font-bold text-gray-900 mb-6">Generate External Content</h2>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
<!-- Draft Form -->
<div class="lg:col-span-2">
<div class="bg-white rounded-lg shadow p-6">
<form id="draft-form">
<div class="space-y-6">
<!-- STEP 1: Content Type -->
<div class="pb-4 border-b border-gray-200">
<h3 class="text-sm font-semibold text-gray-900 mb-3">Step 1: Content Type</h3>
<div class="grid grid-cols-2 gap-3">
<label class="content-type-card">
<input type="radio" name="contentType" value="blog" class="sr-only" checked>
<div class="p-4 border-2 border-gray-200 rounded-lg cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all">
<div class="font-medium text-gray-900">Website Blog</div>
<div class="text-xs text-gray-500 mt-1">Long-form content for agenticgovernance.digital</div>
</div>
</label>
<label class="content-type-card">
<input type="radio" name="contentType" value="letter" class="sr-only">
<div class="p-4 border-2 border-gray-200 rounded-lg cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all">
<div class="font-medium text-gray-900">Letter to Editor</div>
<div class="text-xs text-gray-500 mt-1">200-300 words, article reference required</div>
</div>
</label>
<label class="content-type-card">
<input type="radio" name="contentType" value="oped" class="sr-only">
<div class="p-4 border-2 border-gray-200 rounded-lg cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all">
<div class="font-medium text-gray-900">Op-Ed / Opinion</div>
<div class="text-xs text-gray-500 mt-1">750-1500 words, external publication</div>
</div>
</label>
<label class="content-type-card">
<input type="radio" name="contentType" value="social" class="sr-only">
<div class="p-4 border-2 border-gray-200 rounded-lg cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all">
<div class="font-medium text-gray-900">Social Media</div>
<div class="text-xs text-gray-500 mt-1">LinkedIn, Substack, Medium</div>
</div>
</label>
</div>
</div>
<!-- STEP 2: Publication Target (conditional) -->
<div id="publication-section" class="pb-4 border-b border-gray-200 hidden">
<h3 class="text-sm font-semibold text-gray-900 mb-3">Step 2: Publication Target</h3>
<select id="publication-target" name="publicationTarget"
class="block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
<option value="">Select publication...</option>
</select>
<!-- Publication info display -->
<div id="publication-info" class="mt-4 hidden p-4 bg-gray-50 rounded-md">
<dl class="space-y-2 text-sm">
<div>
<dt class="font-medium text-gray-700">Word Count:</dt>
<dd class="text-gray-600" id="pub-word-count">-</dd>
</div>
<div>
<dt class="font-medium text-gray-700">Submission:</dt>
<dd class="text-gray-600" id="pub-submission">-</dd>
</div>
<div>
<dt class="font-medium text-gray-700">Response Time:</dt>
<dd class="text-gray-600" id="pub-response">-</dd>
</div>
</dl>
</div>
<!-- Publication-Specific Topic Suggestions -->
<button type="button" id="suggest-topics-btn"
class="mt-4 px-4 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 disabled:bg-gray-400 disabled:cursor-not-allowed hidden">
<span id="suggest-topics-text">✨ Get Topic Suggestions for This Publication</span>
<span id="suggest-topics-loader" class="hidden">⏳ Generating...</span>
</button>
<!-- Topic Suggestions Display -->
<div id="topic-suggestions" class="mt-4 hidden"></div>
</div>
<!-- STEP 3: Article Reference (for letters only) -->
<div id="article-reference-section" class="pb-4 border-b border-gray-200 hidden">
<h3 class="text-sm font-semibold text-gray-900 mb-3">Step 3: Article Reference</h3>
<div class="space-y-3">
<div>
<label for="article-title" class="block text-sm font-medium text-gray-700">Article Title *</label>
<input type="text" id="article-title" name="articleTitle"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
placeholder="e.g., AI Regulation in Brussels">
</div>
<div>
<label for="article-date" class="block text-sm font-medium text-gray-700">Publication Date *</label>
<input type="date" id="article-date" name="articleDate"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label for="main-point" class="block text-sm font-medium text-gray-700">Your Main Point *</label>
<textarea id="main-point" name="mainPoint" rows="3"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
placeholder="e.g., EU AI Act needs stronger enforcement mechanisms to be effective"></textarea>
</div>
</div>
</div>
<!-- STEP 4: Topic/Theme (for blog/oped) -->
<div id="topic-section" class="pb-4 border-b border-gray-200">
<h3 class="text-sm font-semibold text-gray-900 mb-3">
<span id="topic-step-label">Step 2</span>: Topic & Content
</h3>
<div class="space-y-3">
<div>
<label for="topic" class="block text-sm font-medium text-gray-700">Topic *</label>
<input type="text" id="topic" name="topic" required
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
placeholder="e.g., Understanding AI Boundary Enforcement in Production Systems">
</div>
<div>
<label for="focus" class="block text-sm font-medium text-gray-700">Specific Focus (Optional)</label>
<input type="text" id="focus" name="focus"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
placeholder="e.g., Real-world implementation challenges, case studies, best practices">
</div>
</div>
</div>
<!-- STEP 5: Audience & Context -->
<div id="context-section" class="pb-4 border-b border-gray-200">
<h3 class="text-sm font-semibold text-gray-900 mb-3">
<span id="context-step-label">Step 3</span>: Audience & Context
</h3>
<div class="space-y-3">
<div>
<label for="audience" class="block text-sm font-medium text-gray-700">Target Audience *</label>
<select id="audience" name="audience" required
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
<option value="">Select audience...</option>
<option value="research">Research (Academic, AI safety specialists)</option>
<option value="implementer">Implementer (Engineers, architects)</option>
<option value="leader">Leader (Policy makers, executives)</option>
<option value="general">General (Mixed backgrounds)</option>
</select>
</div>
<div>
<label for="tone" class="block text-sm font-medium text-gray-700">Tone & Approach</label>
<select id="tone" name="tone"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
<option value="standard">Standard (Professional, balanced)</option>
<option value="academic">Academic (Rigorous, citations)</option>
<option value="practical">Practical (Action-oriented)</option>
<option value="strategic">Strategic (High-level, business)</option>
<option value="conversational">Conversational (Accessible, engaging)</option>
</select>
</div>
<div>
<label for="culture" class="block text-sm font-medium text-gray-700">Cultural Context</label>
<select id="culture" name="culture"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
<option value="universal">Universal (Culture-neutral)</option>
<option value="indigenous">Indigenous (Māori, First Nations)</option>
<option value="global-south">Global South (Emerging economies)</option>
<option value="asia-pacific">Asia-Pacific</option>
<option value="european">European</option>
<option value="north-american">North American</option>
</select>
</div>
<div>
<label for="language" class="block text-sm font-medium text-gray-700">Language</label>
<select id="language" name="language"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
<option value="en">English</option>
<option value="mi">Te Reo Māori</option>
<option value="es">Español (Spanish)</option>
<option value="fr">Français (French)</option>
<option value="de">Deutsch (German)</option>
<option value="zh">中文 (Chinese)</option>
<option value="ja">日本語 (Japanese)</option>
</select>
</div>
</div>
</div>
<!-- Submit -->
<div class="flex items-center justify-between pt-2">
<button type="submit" id="draft-btn"
class="bg-blue-600 text-white px-6 py-2 rounded-md font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Generate Draft
</button>
<span id="draft-status" class="text-sm text-gray-500"></span>
</div>
</div>
</form>
</div>
</div>
<!-- Quick Actions -->
<div class="space-y-4">
<div class="bg-white rounded-lg shadow p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Quick Actions</h3>
<div class="space-y-3">
<button id="suggest-topics-btn"
class="w-full text-left px-4 py-3 bg-gray-50 hover:bg-gray-100 rounded-md border border-gray-200">
<div class="font-medium text-gray-900">Suggest Topics</div>
<div class="text-sm text-gray-500">Get AI topic ideas for editorial calendar</div>
</button>
<button id="analyze-content-btn"
class="w-full text-left px-4 py-3 bg-gray-50 hover:bg-gray-100 rounded-md border border-gray-200">
<div class="font-medium text-gray-900">Analyze Content</div>
<div class="text-sm text-gray-500">Check existing content for compliance</div>
</button>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<h3 class="text-lg font-medium text-gray-900 mb-2">Statistics</h3>
<div class="space-y-3">
<div>
<div class="text-2xl font-bold text-gray-900" id="stat-pending-drafts">-</div>
<div class="text-sm text-gray-500">Pending Drafts</div>
</div>
<div>
<div class="text-2xl font-bold text-gray-900" id="stat-published-posts">-</div>
<div class="text-sm text-gray-500">Published Posts</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Validation Section -->
<div id="validation-section">
<h2 class="text-2xl font-bold text-gray-900 mb-6">Pre-Submission Review & Validation</h2>
<p class="text-sm text-gray-600 mb-4">Articles awaiting final validation and submission package preparation before sending to publications.</p>
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<div class="flex">
<div class="flex-shrink-0">
<svg aria-hidden="true" class="h-5 w-5 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/>
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-blue-800">Two-Level Validation</h3>
<div class="mt-2 text-sm text-blue-700">
<p>Articles are validated for both <strong>content similarity</strong> (substantive differences in arguments) and <strong>title similarity</strong> (avoiding confusion in the same market). Both checks must pass before submission.</p>
</div>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b border-gray-200">
<div class="flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-900">Pending Review Articles</h3>
<button id="refresh-validation-btn" class="text-sm text-blue-600 hover:text-blue-800">
Refresh
</button>
</div>
</div>
<div id="validation-list" class="divide-y divide-gray-200">
<div class="px-6 py-8 text-center text-gray-500">Loading articles...</div>
</div>
</div>
</div>
<!-- Review Queue Section -->
<div id="queue-section" class="hidden">
<h2 class="text-2xl font-bold text-gray-900 mb-6">AI-Generated Draft Approval Queue</h2>
<p class="text-sm text-gray-600 mb-4">AI-generated drafts requiring human review and approval before becoming articles.</p>
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b border-gray-200">
<div class="flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-900">Pending Drafts</h3>
<button id="refresh-queue-btn" class="text-sm text-blue-600 hover:text-blue-800">
Refresh
</button>
</div>
</div>
<div id="draft-queue" class="divide-y divide-gray-200">
<div class="px-6 py-8 text-center text-gray-500">Loading queue...</div>
</div>
</div>
</div>
<!-- Guidelines Section -->
<div id="guidelines-section" class="hidden">
<h2 class="text-2xl font-bold text-gray-900 mb-6">Editorial Guidelines</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="bg-white rounded-lg shadow p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Writing Standards</h3>
<dl id="editorial-standards" class="space-y-3">
<div class="text-center text-gray-500">Loading guidelines...</div>
</dl>
</div>
<div class="bg-white rounded-lg shadow p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Forbidden Patterns</h3>
<ul id="forbidden-patterns" class="space-y-2">
<li class="text-center text-gray-500">Loading patterns...</li>
</ul>
</div>
</div>
<div class="mt-6 bg-white rounded-lg shadow p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Core Principles</h3>
<ul id="core-principles" class="grid grid-cols-1 md:grid-cols-2 gap-4">
<li class="text-center text-gray-500">Loading principles...</li>
</ul>
</div>
</div>
<!-- Published Posts Section -->
<div id="published-section" class="hidden">
<h2 class="text-2xl font-bold text-gray-900 mb-6">Published Website Content</h2>
<p class="text-sm text-gray-600 mb-4">Articles published on the Tractatus website. These are different from outreach articles submitted to external publications.</p>
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b border-gray-200">
<div class="flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-900">Published Articles</h3>
<button id="refresh-published-btn" class="text-sm text-blue-600 hover:text-blue-800">
Refresh
</button>
</div>
</div>
<div id="published-list" class="divide-y divide-gray-200">
<div class="px-6 py-8 text-center text-gray-500">Loading published posts...</div>
</div>
</div>
</div>
</div>
<!-- Modals -->
<div id="modal-container"></div>
<script src="/js/admin/blog-curation.js?v=1761220417"></script>
<script src="/js/admin/blog-curation-enhanced.js?v=1761220417"></script>
<script src="/js/admin/blog-validation.js?v=1761220417"></script>
</body>
</html>