From 2a9a3be0f0ad3005860fe02efa014329e41348e1 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Sat, 23 May 2026 02:01:19 -0400 Subject: [PATCH] Add PATCH note route and row_count to change log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PATCH /api/log/:logid — saves note updates to pf.log (was missing, frontend call was silently failing) - GET /api/versions/:id/log — joins fc_table to return row_count per entry so the change log modal shows rows affected instead of '—' Co-Authored-By: Claude Sonnet 4.6 --- routes/log.js | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/routes/log.js b/routes/log.js index eb1c42c..85f84f8 100644 --- a/routes/log.js +++ b/routes/log.js @@ -4,11 +4,31 @@ const { fcTable } = require('../lib/utils'); module.exports = function(pool) { const router = express.Router(); - // list all log entries for a version, newest first + // list all log entries for a version, newest first, with row counts from fc_table router.get('/versions/:id/log', async (req, res) => { try { + const verResult = await pool.query(` + SELECT v.*, s.tname + FROM pf.version v + JOIN pf.source s ON s.id = v.source_id + WHERE v.id = $1 + `, [req.params.id]); + if (verResult.rows.length === 0) return res.status(404).json({ error: 'Version not found' }); + + const { tname, id: version_id } = verResult.rows[0]; + const table = fcTable(tname, version_id); + const result = await pool.query( - `SELECT * FROM pf.log WHERE version_id = $1 ORDER BY stamp DESC`, + `SELECT l.*, + counts.row_count + FROM pf.log l + LEFT JOIN ( + SELECT pf_logid, count(*)::int AS row_count + FROM ${table} + GROUP BY pf_logid + ) counts ON counts.pf_logid = l.id + WHERE l.version_id = $1 + ORDER BY l.stamp DESC`, [req.params.id] ); res.json(result.rows); @@ -18,6 +38,22 @@ module.exports = function(pool) { } }); + // update note on a log entry + router.patch('/log/:logid', async (req, res) => { + const { note } = req.body; + try { + const result = await pool.query( + `UPDATE pf.log SET note = $1 WHERE id = $2 RETURNING *`, + [note ?? null, parseInt(req.params.logid)] + ); + if (result.rows.length === 0) return res.status(404).json({ error: 'Log entry not found' }); + res.json(result.rows[0]); + } catch (err) { + console.error(err); + res.status(500).json({ error: err.message }); + } + }); + // undo an operation — deletes all forecast rows with this logid, then the log entry // two separate queries in a transaction to avoid FK ordering issues router.delete('/log/:logid', async (req, res) => {