feat(admin): add pending tag suggestions detector

This commit is contained in:
Jennie Robinson Faber 2026-04-08 11:12:52 +01:00
parent ab3f0a8b39
commit 0dc1b6ddbc
2 changed files with 72 additions and 0 deletions

View file

@ -226,4 +226,35 @@ export async function detectEventsNearCapacity() {
}
}
export async function detectPendingTagSuggestions() {
await connectDB()
const suggestions = await TagSuggestion
.find({ status: 'pending' })
.select('_id')
.lean()
if (suggestions.length === 0) {
return {
type: 'tag_suggestions_pending',
severity: 'attention',
title: 'Pending tag suggestions',
items: []
}
}
return {
type: 'tag_suggestions_pending',
severity: 'attention',
title: 'Pending tag suggestions',
items: [
{
id: 'tag-suggestions',
label: `${suggestions.length} pending tag suggestion${suggestions.length === 1 ? '' : 's'}`,
sublabel: 'Review and approve in Tags',
href: '/admin/tags'
}
],
// signature is computed from the underlying suggestion ids, not the rendered item id
signatureIds: suggestions.map((s) => String(s._id))
}
}
// Aggregator lands in task 8.

View file

@ -61,6 +61,8 @@ import {
import Member from '../../../server/models/member.js'
import PreRegistration from '../../../server/models/preRegistration.js'
import Event from '../../../server/models/event.js'
import { detectPendingTagSuggestions } from '../../../server/utils/adminAlerts.js'
import TagSuggestion from '../../../server/models/tagSuggestion.js'
describe('adminAlerts module shell', () => {
describe('ALERT_THRESHOLDS', () => {
@ -349,4 +351,43 @@ describe('adminAlerts module shell', () => {
})
})
})
describe('tag suggestion alert', () => {
beforeEach(() => {
vi.clearAllMocks()
})
function mockTagSuggestionFind(result) {
TagSuggestion.find.mockReturnValue({
select: vi.fn().mockReturnValue({
lean: vi.fn().mockResolvedValue(result)
})
})
}
it('returns a single aggregated item with the count', async () => {
mockTagSuggestionFind([
{ _id: 't1' }, { _id: 't2' }, { _id: 't3' }
])
const alert = await detectPendingTagSuggestions()
expect(alert.type).toBe('tag_suggestions_pending')
expect(alert.severity).toBe('attention')
expect(alert.items).toHaveLength(1)
expect(alert.items[0]).toEqual({
id: 'tag-suggestions',
label: '3 pending tag suggestions',
sublabel: 'Review and approve in Tags',
href: '/admin/tags'
})
expect(TagSuggestion.find).toHaveBeenCalledWith({ status: 'pending' })
})
it('returns an empty list when nothing is pending', async () => {
mockTagSuggestionFind([])
const alert = await detectPendingTagSuggestions()
expect(alert.items).toEqual([])
})
})
})