diff --git a/backend/src/routes/templates.js b/backend/src/routes/templates.js index fca871a..d790c95 100644 --- a/backend/src/routes/templates.js +++ b/backend/src/routes/templates.js @@ -122,6 +122,17 @@ export async function templateRoutes(app) { return rows[0] }) + // DELETE /api/templates/:id — stops the recurring schedule; any tasks already + // spawned from it are detached (template_id cleared) rather than blocked or + // cascaded, so they remain as ordinary task history. + app.delete('/api/templates/:id', { preHandler: requireCap('manage_templates') }, async (req, reply) => { + const { rows: existing } = await pool.query('SELECT id FROM task_templates WHERE id = $1', [req.params.id]) + if (!existing.length) return reply.status(404).send({ error: 'Template not found' }) + await pool.query('UPDATE tasks SET template_id = NULL WHERE template_id = $1', [req.params.id]) + await pool.query('DELETE FROM task_templates WHERE id = $1', [req.params.id]) + return { ok: true } + }) + // POST /api/templates/run-due — manually trigger the scheduler sweep app.post('/api/templates/run-due', { preHandler: requireCap('manage_templates') }, async (req) => { const spawned = await spawnDueTemplates(req.log) diff --git a/frontend/src/api.ts b/frontend/src/api.ts index 721d1a5..afd4793 100644 --- a/frontend/src/api.ts +++ b/frontend/src/api.ts @@ -199,6 +199,9 @@ export function createTemplate(body: Record): Promise