feat(admin): add standalone submission package modal support

- Add data-is-standalone flag to manage-submission buttons
- Create openStandaloneSubmissionModal function for packages without blog posts
- Update renderOverviewTab to handle null article (standalone submissions)
- Display standalone submission notice with purple badge
- Load submission data directly via /api/submissions/{id}
- Differentiate UI labels (Submitted vs Published dates)
- Files modified: blog-validation.js, submission-modal-enhanced.js
This commit is contained in:
TheFlow 2025-10-24 11:06:22 +13:00
parent c4f370cc6e
commit 9729878f96
3 changed files with 91 additions and 21 deletions

View file

@ -43,8 +43,8 @@
"last_deliberation": null
},
"FileEditHook": {
"timestamp": "2025-10-23T22:02:15.582Z",
"file": "/home/theflow/projects/tractatus/public/js/admin/blog-curation-enhanced.js",
"timestamp": "2025-10-23T22:06:08.878Z",
"file": "/home/theflow/projects/tractatus/public/js/admin/submission-modal-enhanced.js",
"result": "passed"
},
"FileWriteHook": {
@ -58,25 +58,25 @@
"tokens": 30000
},
"alerts": [],
"last_updated": "2025-10-23T22:02:15.582Z",
"last_updated": "2025-10-23T22:06:08.878Z",
"initialized": true,
"framework_components": {
"CrossReferenceValidator": {
"message": 0,
"tokens": 0,
"timestamp": "2025-10-23T22:02:25.695Z",
"last_validation": "2025-10-23T22:02:25.694Z",
"validations_performed": 766
"timestamp": "2025-10-23T22:06:19.032Z",
"last_validation": "2025-10-23T22:06:19.032Z",
"validations_performed": 773
},
"BashCommandValidator": {
"message": 0,
"tokens": 0,
"timestamp": null,
"last_validation": "2025-10-23T22:02:25.695Z",
"validations_performed": 414,
"last_validation": "2025-10-23T22:06:19.033Z",
"validations_performed": 417,
"blocks_issued": 37
}
},
"action_count": 414,
"action_count": 417,
"auto_compact_events": []
}

View file

@ -221,7 +221,8 @@ async function loadValidationArticles() {
<div class="ml-4 flex items-center gap-2 flex-wrap">
<button class="manage-submission px-4 py-2 bg-green-600 text-white rounded-md text-sm hover:bg-green-700"
data-article-id="${itemId}"
data-submission-id="${submission ? submission._id : ''}">
data-submission-id="${submission ? submission._id : ''}"
data-is-standalone="${isStandalone ? 'true' : 'false'}">
${isStandalone ? 'View Package' : 'Manage Submission'}
</button>
${!isStandalone ? `
@ -843,6 +844,41 @@ let currentSubmissionArticleId = null;
let currentSubmissionId = null;
let currentArticleData = null;
/**
* Open modal for standalone submission package (no blog post)
*/
async function openStandaloneSubmissionModal(submissionId) {
const modal = document.getElementById('manage-submission-modal');
if (!modal) {
createEnhancedSubmissionModal();
}
try {
// Load submission data directly
const response = await apiCall(`/api/submissions/${submissionId}`);
if (!response.ok) throw new Error('Failed to load submission data');
const submissionResponse = await response.json();
currentSubmission = submissionResponse.data || submissionResponse;
// No article for standalone submissions
currentArticle = null;
// Update modal title
document.getElementById('modal-title').textContent = `Submission Package: ${currentSubmission.title}`;
// Show modal
document.getElementById('manage-submission-modal').classList.remove('hidden');
// Load overview tab
switchTab('overview');
} catch (error) {
console.error('Error loading standalone submission:', error);
alert('Failed to load submission package. Please try again.');
}
}
/**
* Initialize Manage Submission button handlers
*/
@ -852,7 +888,15 @@ function initManageSubmissionHandlers() {
if (e.target.classList.contains('manage-submission')) {
const articleId = e.target.dataset.articleId;
const submissionId = e.target.dataset.submissionId;
openManageSubmissionModal(articleId, submissionId || null);
const isStandalone = e.target.dataset.isStandalone === 'true';
if (isStandalone) {
// For standalone submissions, open with submission ID only
openStandaloneSubmissionModal(articleId);
} else {
// For blog-linked submissions, open with article ID
openManageSubmissionModal(articleId, submissionId || null);
}
}
});
}

View file

@ -224,7 +224,11 @@ function renderOverviewTab() {
const submission = currentSubmission || {};
const article = currentArticle;
const wordCount = article.content ? article.content.split(/\s+/).length : 0;
// Handle standalone submissions (no article)
const isStandalone = !article;
const title = isStandalone ? submission.title : article.title;
const subtitle = isStandalone ? '' : (article.subtitle || '');
const wordCount = isStandalone ? (submission.wordCount || 0) : (article.content ? article.content.split(/\s+/).length : 0);
const publicationName = submission.publicationName || 'Not assigned';
const status = submission.status || 'draft';
@ -235,26 +239,48 @@ function renderOverviewTab() {
if (submission.documents?.authorBio?.versions?.length > 0) completionScore += 25;
if (submission.publicationId) completionScore += 25;
const excerptText = article.excerpt || (article.content?.substring(0, 300) + '...') || 'No content available';
const publishedDate = article.published_at ? new Date(article.published_at).toLocaleDateString() : 'N/A';
// Get content/excerpt - for standalone, use document content if available
let excerptText = 'No content available';
if (isStandalone) {
const mainArticle = submission.documents?.mainArticle?.versions?.[0];
if (mainArticle?.content) {
excerptText = mainArticle.content.substring(0, 300) + '...';
}
} else {
excerptText = article.excerpt || (article.content?.substring(0, 300) + '...') || 'No content available';
}
const publishedDate = isStandalone
? (submission.submittedAt ? new Date(submission.submittedAt).toLocaleDateString() : 'Not submitted')
: (article.published_at ? new Date(article.published_at).toLocaleDateString() : 'N/A');
return `
<div class="space-y-6">
<!-- Article Preview -->
${isStandalone ? `
<!-- Standalone Submission Notice -->
<div class="bg-purple-50 border border-purple-200 rounded-lg p-4">
<div class="flex items-center gap-2">
<span class="text-purple-600 font-semibold">📦 Standalone Submission Package</span>
<span class="text-sm text-purple-600">This is a direct submission without an associated blog post</span>
</div>
</div>
` : ''}
<!-- Article/Submission Preview -->
<div class="bg-gray-50 rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Article Preview</h3>
<h3 class="text-lg font-semibold text-gray-900 mb-4">${isStandalone ? 'Submission' : 'Article'} Preview</h3>
<div class="prose max-w-none">
<h4 class="text-xl font-bold mb-2">${escapeHtml(article.title)}</h4>
<div class="text-sm text-gray-600 mb-4">
${escapeHtml(article.subtitle || '')}
</div>
<h4 class="text-xl font-bold mb-2">${escapeHtml(title)}</h4>
${subtitle ? `<div class="text-sm text-gray-600 mb-4">
${escapeHtml(subtitle)}
</div>` : ''}
<div class="text-gray-700 line-clamp-6">
${escapeHtml(excerptText)}
</div>
</div>
<div class="mt-4 flex items-center space-x-4 text-sm text-gray-600">
<span><strong>Word Count:</strong> ${wordCount.toLocaleString()}</span>
<span><strong>Published:</strong> ${publishedDate}</span>
<span><strong>${isStandalone ? 'Submitted' : 'Published'}:</strong> ${publishedDate}</span>
</div>
</div>