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:
@@ -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 }),
|
||||
|
||||
Reference in New Issue
Block a user