feat(ui): project card Tasks + Linked references sections; GET /api/projects/:id/links

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
root
2026-06-05 00:28:17 +10:00
parent dbf84559de
commit 922b289cae
3 changed files with 44 additions and 0 deletions

View File

@@ -1,6 +1,9 @@
import { Router } from 'express';
import { z } from 'zod';
import * as repo from '../../db/repos/projects.js';
import * as links from '../../db/repos/links.js';
import * as pagesRepo from '../../db/repos/pages.js';
import * as refsRepo from '../../db/repos/refs.js';
import { validate } from '../validate.js';
import { NotFoundError, ValidationError, asyncWrap } from '../errors.js';
import { requireWrite, divertToPending } from '../cap.js';
@@ -80,6 +83,22 @@ router.patch('/:id',
})
);
// Linked references (entity_links FROM this project → pages/refs), with titles resolved.
router.get('/:id/links',
validate({ params: idParams }),
asyncWrap(async (req, res) => {
const rows = await links.listFrom('project', req.params.id);
const out = [];
for (const l of rows) {
let title = null;
if (l.to_type === 'page') { const p = await pagesRepo.getById(l.to_id); title = p?.title; }
else if (l.to_type === 'ref') { const r = await refsRepo.getById(l.to_id); title = r?.title || r?.source_url; }
if (title) out.push({ id: l.id, to_type: l.to_type, to_id: l.to_id, title, relation: l.relation });
}
res.json(out);
})
);
// Research stub — owner asks Eithan (later) to research this project.
router.post('/:id/research',
validate({ params: idParams }),