From 763e7be6cae8ddab7d81d655ad26ee84b0e8c2c6 Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Wed, 26 Aug 2026 11:58:52 +0000 Subject: [PATCH] Add delete action for recurring templates There was no way to remove a template once created (e.g. test/scratch recurring tasks) - only edit/pause via active. DELETE /api/templates/:id detaches any tasks already spawned from it (template_id cleared) rather than blocking on the FK or cascading, so existing task history survives as ordinary one-off tasks while the recurring schedule itself is removed. Delete button in the edit modal footer, only shown when editing an existing template - not on new/duplicate. Co-Authored-By: Claude Sonnet 5 --- backend/src/routes/templates.js | 11 +++++++++++ frontend/src/api.ts | 3 +++ frontend/src/pages/Recurring.tsx | 24 ++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) 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