polish: cleanup unused code, i18n gaps, a11y, error handling

- Removed unused ApproverMultiSelect imports (ArtefactDetailPanel, TranslationDetailPanel)
- Removed stale editProjectId/editCampaignId state from ArtefactDetailPanel
- Added 3 missing i18n keys (selectVersionFirst, pendingReviewInfo, noReviewInfo)
- Added error toast on link picker API failure (PostDetail)
- Added ARIA attributes to PortalSelect (role=combobox, aria-expanded, listbox, option)
- Deleted test screenshots from project root
- Simplified artefact creation modal: title + type only (removed brand/project/campaign/approver/description)
- Cleaned up ArtefactDetailPanel props (removed unused projects/campaigns)
- Translation submit-review: requires source_content before allowing review
- Artefact submit-review: requires at least one attachment for design/video
- Translation reviewer moved to Review tab (single select, mandatory)
- Server blocks translation submit without reviewer

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
fahed
2026-03-16 15:48:19 +03:00
parent eb23931ce0
commit 16a94a2f19
12 changed files with 156 additions and 90 deletions
+25 -2
View File
@@ -4205,6 +4205,22 @@ app.post('/api/artefacts/:id/submit-review', requireAuth, async (req, res) => {
return res.status(403).json({ error: 'You can only submit your own artefacts' });
}
// Design/video must have at least one attachment uploaded
if (existing.type === 'design' || existing.type === 'video') {
const versions = await nocodb.list('ArtefactVersions', {
where: `(artefact_id,eq,${sanitizeWhereValue(existing.Id)})`,
sort: '-version_number', limit: 1,
});
if (versions.length > 0) {
const attachments = await nocodb.list('ArtefactAttachments', {
where: `(version_id,eq,${versions[0].Id})`, limit: 1,
});
if (attachments.length === 0) {
return res.status(400).json({ error: 'Upload at least one file before submitting for review' });
}
}
}
const approverIds = parseApproverIds(existing.approver_ids);
if (approverIds.length === 0) {
return res.status(400).json({ error: 'Select a reviewer before submitting for review' });
@@ -4995,8 +5011,6 @@ app.get('/api/translations/:id', requireAuth, async (req, res) => {
app.post('/api/translations', requireAuth, async (req, res) => {
const { title, source_language, source_content, brand_id, post_id, approver_ids, copy_type } = req.body;
if (!title) return res.status(400).json({ error: 'Title is required' });
if (!source_language) return res.status(400).json({ error: 'Source language is required' });
if (!source_content) return res.status(400).json({ error: 'Source content is required' });
try {
const created = await nocodb.create('Translations', {
@@ -5286,6 +5300,15 @@ app.post('/api/translations/:id/submit-review', requireAuth, async (req, res) =>
return res.status(403).json({ error: 'You can only submit your own translations' });
}
if (!existing.source_content || !existing.source_content.trim()) {
return res.status(400).json({ error: 'Add content before submitting for review' });
}
const approverIds = parseApproverIds(existing.approver_ids);
if (approverIds.length === 0) {
return res.status(400).json({ error: 'Select a reviewer before submitting for review' });
}
const token = require('crypto').randomUUID();
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + DEFAULTS.tokenExpiryDays);