feat: Add spec_path field — link tasks to git documentation
- spec_path column added to tasks table - API POST/PATCH support spec_path field - Discord /tasks detail view shows '📄 Full Spec' link to Gitea when spec exists - Backfilled 7 existing tasks with spec directory paths Architecture: Database tracks state, Git stores documentation, they link to each other. Chronicler #78 | firefrost-services
This commit is contained in:
@@ -166,6 +166,11 @@ async function handleTaskDetail(interaction, taskNumber) {
|
||||
embed.addFields({ name: 'Tags', value: t.tags.map(tag => `\`${tag}\``).join(' '), inline: false });
|
||||
}
|
||||
|
||||
if (t.spec_path) {
|
||||
const specUrl = `https://git.firefrostgaming.com/firefrost-gaming/firefrost-operations-manual/src/branch/master/${t.spec_path}`;
|
||||
embed.addFields({ name: '📄 Full Spec', value: `[View in Gitea](${specUrl})`, inline: false });
|
||||
}
|
||||
|
||||
if (t.completed_at) {
|
||||
const completedDate = new Date(t.completed_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
|
||||
embed.addFields({ name: 'Completed', value: `${completedDate}${t.completed_by ? ` by ${t.completed_by}` : ''}`, inline: false });
|
||||
|
||||
@@ -454,7 +454,7 @@ router.get('/tasks/summary', async (req, res) => {
|
||||
// POST /api/internal/tasks — Create a new task
|
||||
router.post('/tasks', async (req, res) => {
|
||||
try {
|
||||
const { title, description, priority, owner, tags } = req.body;
|
||||
const { title, description, priority, owner, tags, spec_path } = req.body;
|
||||
if (!title) return res.status(400).json({ error: 'Title required' });
|
||||
|
||||
// Auto-assign next task number
|
||||
@@ -462,9 +462,9 @@ router.post('/tasks', async (req, res) => {
|
||||
const taskNumber = maxResult.rows[0].next;
|
||||
|
||||
const result = await db.query(
|
||||
`INSERT INTO tasks (task_number, title, description, priority, owner, tags)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`,
|
||||
[taskNumber, title, description || null, priority || 'medium', owner || 'unassigned', tags || null]
|
||||
`INSERT INTO tasks (task_number, title, description, priority, owner, tags, spec_path)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *`,
|
||||
[taskNumber, title, description || null, priority || 'medium', owner || 'unassigned', tags || null, spec_path || null]
|
||||
);
|
||||
console.log(`📋 [Tasks] Created #${taskNumber}: ${title}`);
|
||||
res.json({ success: true, task: result.rows[0] });
|
||||
@@ -478,7 +478,7 @@ router.post('/tasks', async (req, res) => {
|
||||
router.patch('/tasks/:id', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { status, priority, owner, title, description, completed_by } = req.body;
|
||||
const { status, priority, owner, title, description, completed_by, spec_path } = req.body;
|
||||
|
||||
const updates = [];
|
||||
const params = [];
|
||||
@@ -489,6 +489,7 @@ router.patch('/tasks/:id', async (req, res) => {
|
||||
if (owner) { p++; updates.push(`owner = $${p}`); params.push(owner); }
|
||||
if (title) { p++; updates.push(`title = $${p}`); params.push(title); }
|
||||
if (description !== undefined) { p++; updates.push(`description = $${p}`); params.push(description); }
|
||||
if (spec_path !== undefined) { p++; updates.push(`spec_path = $${p}`); params.push(spec_path); }
|
||||
|
||||
// Auto-set completed_at when marking done
|
||||
if (status === 'done') {
|
||||
|
||||
Reference in New Issue
Block a user