diff --git a/CHANGES.rst b/CHANGES.rst index f98982f3..00144767 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,9 +7,10 @@ Changelog for Isso New Features ^^^^^^^^^^^^ -- Add option to show/hide website field in comment form (`#1111`_, pkvach) +- Update comment counts in the admin interface dynamically after moderation. (`#1113`_, pkvach) .. _#1111: https://github.com/isso-comments/isso/pull/1111 +.. _#1113: https://github.com/isso-comments/isso/pull/1113 0.14.0 (2026-03-26) -------------------- diff --git a/isso/js/admin.js b/isso/js/admin.js index 27619b63..fab54bde 100644 --- a/isso/js/admin.js +++ b/isso/js/admin.js @@ -24,12 +24,37 @@ function fade(element) { op -= op * 0.1; }, 10); } +const modeCountIds = {1: 'count-mode-1', 2: 'count-mode-2', 4: 'count-mode-4'}; + +function getCommentMode(com_id) { + const commentEl = document.getElementById('isso-' + com_id); + if (!commentEl) return null; + const mode = parseInt(commentEl.dataset.mode, 10); + return isNaN(mode) ? null : mode; +} + +function updateCountBadge(modeId, delta) { + const el = document.getElementById(modeId); + if (!el) return; + const countEl = el.querySelector('.count'); + if (!countEl) return; + const currentCount = parseInt(countEl.textContent, 10) || 0; + countEl.textContent = Math.max(0, currentCount + delta); +} + function moderate(com_id, hash, action, isso_host_script) { - ajax({method: "POST", - url: isso_host_script + "/id/" + com_id + "/" + action + "/" + hash, - success: function(){ - fade(document.getElementById("isso-" + com_id)); - }}); + var fromMode = getCommentMode(com_id); + ajax({method: "POST", + url: isso_host_script + "/id/" + com_id + "/" + action + "/" + hash, + success: function(){ + fade(document.getElementById("isso-" + com_id)); + if (fromMode && modeCountIds[fromMode]) { + updateCountBadge(modeCountIds[fromMode], -1); + } + if (action === 'activate' && modeCountIds[1]) { + updateCountBadge(modeCountIds[1], +1); + } + }}); } function edit(com_id, hash, author, email, website, comment, isso_host_script) { ajax({method: "POST", @@ -134,3 +159,7 @@ function toggleTooltip(tooltipContainer) { const tooltipText = tooltipContainer.querySelector(".search-tooltip-text"); tooltipText.classList.toggle("show"); } + +if (typeof module !== 'undefined') { + module.exports = { getCommentMode, updateCountBadge }; +} diff --git a/isso/js/tests/unit/admin.test.js b/isso/js/tests/unit/admin.test.js new file mode 100644 index 00000000..10e52d7e --- /dev/null +++ b/isso/js/tests/unit/admin.test.js @@ -0,0 +1,71 @@ +/** + * @jest-environment jsdom + */ + +/* Keep the above exactly as-is! + * https://jestjs.io/docs/configuration#testenvironment-string + */ + +const { getCommentMode, updateCountBadge } = require("admin"); + +describe("getCommentMode", () => { + test("returns 1 for a valid comment", () => { + document.body.innerHTML = ` +
+ Valid +
`; + expect(getCommentMode(1)).toBe(1); + }); + + test("returns 2 for a pending comment", () => { + document.body.innerHTML = ` +
+ Pending +
`; + expect(getCommentMode(2)).toBe(2); + }); + + test("returns 4 for a staled comment", () => { + document.body.innerHTML = ` +
+ Staled +
`; + expect(getCommentMode(3)).toBe(4); + }); + + test("returns null when comment element does not exist", () => { + document.body.innerHTML = ""; + expect(getCommentMode(999)).toBeNull(); + }); +}); + +describe("updateCountBadge", () => { + test("decrements the count", () => { + document.body.innerHTML = `Pending (5)`; + updateCountBadge("count-mode-2", -1); + expect(document.getElementById("count-mode-2").querySelector('.count').textContent).toBe("4"); + }); + + test("increments the count", () => { + document.body.innerHTML = `Valid (1)`; + updateCountBadge("count-mode-1", +1); + expect(document.getElementById("count-mode-1").querySelector('.count').textContent).toBe("2"); + }); + + test("does not decrement below zero", () => { + document.body.innerHTML = `Pending (0)`; + updateCountBadge("count-mode-2", -1); + expect(document.getElementById("count-mode-2").querySelector('.count').textContent).toBe("0"); + }); + + test("does nothing when count span is absent", () => { + document.body.innerHTML = `Pending (3)`; + expect(() => updateCountBadge("count-mode-2", -1)).not.toThrow(); + expect(document.getElementById("count-mode-2").textContent).toBe("Pending (3)"); + }); + + test("does nothing for a nonexistent element", () => { + document.body.innerHTML = ""; + expect(() => updateCountBadge("count-mode-99", -1)).not.toThrow(); + }); +}); diff --git a/isso/templates/admin.html b/isso/templates/admin.html index 1d7f948e..3ff930a8 100644 --- a/isso/templates/admin.html +++ b/isso/templates/admin.html @@ -24,18 +24,18 @@

Administration

- - Valid ({{counts.get(1, 0)}}) + + Valid ({{counts.get(1, 0)}}) - - Pending ({{counts.get(2, 0)}}) + + Pending ({{counts.get(2, 0)}}) - - Staled ({{counts.get(4, 0)}}) + + Staled ({{counts.get(4, 0)}})
@@ -100,7 +100,7 @@

Administration

{{comment.title}} ({{comment.uri}})

{% endif %} {% endif %} -
+
{% if conf.avatar %}
svg(data-hash='#{{comment.hash}}')