Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -764,11 +764,17 @@ function isEligibleQueueCandidate(result: QueueCandidateCheck | undefined): bool
return !result.locked || !!result.expired || !!result.isOwnLock
}
function isNotFoundError(error: unknown): boolean {
if (!error || typeof error !== 'object') return false
const fetchError = error as { statusCode?: number; response?: { status?: number } }
return fetchError.statusCode === 404 || fetchError.response?.status === 404
}
function notifySkippedQueueProjects(count: number) {
if (count <= 0) return
addNotification({
title: 'Skipped projects',
text: `Skipped ${count} project(s) already moderated or locked by others.`,
text: `Skipped ${count} project(s) already moderated, deleted, or locked by others.`,
type: 'info',
autoCloseMs: 2000,
})
Expand Down Expand Up @@ -799,10 +805,10 @@ async function batchCheckQueueCandidates(
projectIds.map(async (id) => {
const [lockResponse, projectData] = await Promise.all([
moderationQueue.checkLock(id),
useBaseFetch(`project/${id}`, { method: 'GET' }).catch(() => null),
useBaseFetch(`project/${id}`, { method: 'GET' }),
])
const status = (projectData as { status?: string } | null)?.status
const status = (projectData as { status?: string }).status
return {
id,
Expand All @@ -812,14 +818,16 @@ async function batchCheckQueueCandidates(
slug: (projectData as { slug?: string } | null)?.slug,
projectType: (projectData as { project_type?: string } | null)?.project_type,
status,
isProcessing: projectData === null ? true : status === 'processing',
isProcessing: status === 'processing',
}
}),
)
checks.forEach((result, index) => {
if (result.status === 'fulfilled') {
results.set(result.value.id, result.value)
} else if (isNotFoundError(result.reason)) {
results.set(projectIds[index], { locked: false, isProcessing: false })
} else {
results.set(projectIds[index], { locked: false, isProcessing: true })
}
Expand Down Expand Up @@ -966,7 +974,7 @@ async function skipToNextProject() {
debug('[skipToNextProject] No eligible projects in queue')
addNotification({
title: 'No projects available',
text: 'All remaining projects are already moderated or locked by others.',
text: 'All remaining projects are already moderated, deleted, or locked by others.',
type: 'warning',
})
}
Expand Down Expand Up @@ -1636,9 +1644,15 @@ async function sendMessage(status: ProjectStatus) {
}
}
await refreshModerationCaches(threadId)
const willHaveNext = await moderationQueue.completeCurrentProject(projectId, 'completed')
// Set both states together - hasNextProject MUST be set before done
// to avoid the race condition where done=true renders with hasNextProject=false
hasNextProject.value = willHaveNext
done.value = true
clearGeneratedMessageState()
await nextTick()
await refreshModerationCaches(threadId)
await Promise.race([
moderationQueue.releaseLock(projectId),
Expand All @@ -1648,16 +1662,9 @@ async function sendMessage(status: ProjectStatus) {
if (projectFixChanges?.slug) {
const urlType = getProjectTypeForUrlShorthand(projectV2.value.project_type, [], tags.value)
localStorage.setItem('moderation-checklist-finished', projectId)
clearGeneratedMessageState()
await navigateTo(`/${urlType}/${projectFixChanges.slug}/moderation`, { replace: true })
return
}
// Set both states together - hasNextProject MUST be set before done
// to avoid the race condition where done=true renders with hasNextProject=false
hasNextProject.value = willHaveNext
done.value = true
clearGeneratedMessageState()
} catch (error) {
console.error('Error submitting moderation:', error)
addNotification({
Expand Down Expand Up @@ -1720,7 +1727,7 @@ async function endChecklist(status?: string) {
)
addNotification({
title: 'No projects available',
text: 'All remaining projects are already moderated or locked by others.',
text: 'All remaining projects are already moderated, deleted, or locked by others.',
type: 'warning',
})
}
Expand Down
Loading