Member/Ecology revamp.
Some checks failed
Test / vitest (push) Failing after 7m23s
Test / playwright (push) Has been skipped
Test / visual (push) Has been skipped
Test / Notify on failure (push) Successful in 2s

This commit is contained in:
Jennie Robinson Faber 2026-04-14 09:25:09 +01:00
parent fc7ec52574
commit 59d6e97787
31 changed files with 1763 additions and 1010 deletions

View file

@ -2,23 +2,35 @@ import * as z from 'zod'
import WikiArticle from '../../../models/wikiArticle.js'
import { connectDB } from '../../../utils/mongoose.js'
const wikiTagsSchema = z.object({
tags: z.array(z.string())
const wikiUpdateSchema = z.object({
tags: z.array(z.string()).optional(),
hidden: z.boolean().optional()
})
export default defineEventHandler(async (event) => {
await requireAdmin(event)
const body = await validateBody(event, wikiTagsSchema)
const body = await validateBody(event, wikiUpdateSchema)
const id = getRouterParam(event, 'id')
if (body.tags === undefined && body.hidden === undefined) {
throw createError({ statusCode: 400, statusMessage: 'Nothing to update' })
}
await connectDB()
await validateTagSlugs(body.tags)
const update = {}
if (body.tags !== undefined) {
await validateTagSlugs(body.tags)
update.tags = body.tags
}
if (body.hidden !== undefined) {
update.hidden = body.hidden
}
const article = await WikiArticle.findByIdAndUpdate(
id,
{ tags: body.tags },
update,
{ new: true }
)

View file

@ -0,0 +1,34 @@
import * as z from 'zod'
import WikiArticle from '../../../models/wikiArticle.js'
import { connectDB } from '../../../utils/mongoose.js'
const batchVisibilitySchema = z.object({
articleIds: z.array(z.string()).optional(),
collection: z.string().optional(),
hidden: z.boolean()
})
export default defineEventHandler(async (event) => {
await requireAdmin(event)
const body = await validateBody(event, batchVisibilitySchema)
if (!body.articleIds && !body.collection) {
throw createError({
statusCode: 400,
statusMessage: 'Must provide either articleIds or collection'
})
}
await connectDB()
const filter = body.articleIds
? { _id: { $in: body.articleIds } }
: { collection: body.collection }
const result = await WikiArticle.updateMany(filter, {
$set: { hidden: body.hidden }
})
return { modified: result.modifiedCount || 0 }
})

View file

@ -16,7 +16,7 @@ export default defineEventHandler(async (event) => {
}
const articles = await WikiArticle.find(filter)
.select('collection title tags url outlineId publishedAt')
.select('collection title tags hidden url outlineId publishedAt outlineUpdatedAt')
.sort({ collection: 1, title: 1 })
.lean()

View file

@ -1,14 +1,10 @@
import WikiArticle from '../../../models/wikiArticle.js'
import { connectDB } from '../../../utils/mongoose.js'
import { fetchAllDocuments, extractSummary } from '../../../utils/outline.js'
import { syncWikiArticles } from '../../../utils/syncWikiArticles.js'
export default defineEventHandler(async (event) => {
await requireAdmin(event)
// Fetch ALL documents first — if this fails, no DB changes happen
let documents
try {
documents = await fetchAllDocuments()
return await syncWikiArticles()
} catch (err) {
console.error('[wiki-sync] Outline fetch failed:', err)
throw createError({
@ -16,68 +12,4 @@ export default defineEventHandler(async (event) => {
statusMessage: err.statusMessage || 'Failed to fetch documents from Outline'
})
}
await connectDB()
const fetchedOutlineIds = new Set(documents.map((doc) => doc.id))
// Get all existing articles for comparison
const existing = await WikiArticle.find({}, 'outlineId publishedAt')
const existingByOutlineId = new Map(
existing.map((a) => [a.outlineId, a])
)
let created = 0
let updated = 0
let deleted = 0
let errors = 0
// Upsert each fetched document
for (const doc of documents) {
try {
const articleData = {
title: doc.title,
collection: doc.collection?.name || null,
url: doc.url,
summary: extractSummary(doc.text),
publishedAt: doc.publishedAt ? new Date(doc.publishedAt) : new Date(doc.createdAt),
permission: doc.permission || null,
lastSyncedAt: new Date(),
outlineUpdatedAt: doc.updatedAt ? new Date(doc.updatedAt) : null
}
const result = await WikiArticle.findOneAndUpdate(
{ outlineId: doc.id },
{ $set: articleData },
{ upsert: true, new: true, rawResult: true }
)
if (result.lastErrorObject?.updatedExisting) {
updated++
} else {
created++
}
} catch (err) {
console.error(`[wiki-sync] Error upserting doc ${doc.id}:`, err)
errors++
}
}
// Soft-delete articles no longer in Outline
for (const [outlineId, article] of existingByOutlineId) {
if (!fetchedOutlineIds.has(outlineId) && article.publishedAt !== null) {
try {
await WikiArticle.findOneAndUpdate(
{ outlineId },
{ $set: { publishedAt: null, lastSyncedAt: new Date() } }
)
deleted++
} catch (err) {
console.error(`[wiki-sync] Error soft-deleting ${outlineId}:`, err)
errors++
}
}
}
return { created, updated, deleted, errors }
})

View file

@ -0,0 +1,20 @@
import WikiArticle from '../../models/wikiArticle.js'
import { connectDB } from '../../utils/mongoose.js'
export default defineEventHandler(async (event) => {
await connectDB()
const query = getQuery(event)
const limit = Math.min(Math.max(parseInt(query.limit) || 4, 1), 10)
const articles = await WikiArticle.find({
publishedAt: { $ne: null },
hidden: { $ne: true }
})
.sort({ publishedAt: -1 })
.limit(limit)
.select('title url publishedAt')
.lean()
return articles
})