Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
--------------------
Expand Down
39 changes: 34 additions & 5 deletions isso/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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 };
}
71 changes: 71 additions & 0 deletions isso/js/tests/unit/admin.test.js
Original file line number Diff line number Diff line change
@@ -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 = `
<div id="isso-1" data-mode="1">
<span class="note"><span class="label label-valid">Valid</span></span>
</div>`;
expect(getCommentMode(1)).toBe(1);
});

test("returns 2 for a pending comment", () => {
document.body.innerHTML = `
<div id="isso-2" data-mode="2">
<span class="note"><span class="label label-pending">Pending</span></span>
</div>`;
expect(getCommentMode(2)).toBe(2);
});

test("returns 4 for a staled comment", () => {
document.body.innerHTML = `
<div id="isso-3" data-mode="4">
<span class="note"><span class="label label-staled">Staled</span></span>
</div>`;
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 = `<span id="count-mode-2">Pending (<span class="count">5</span>)</span>`;
updateCountBadge("count-mode-2", -1);
expect(document.getElementById("count-mode-2").querySelector('.count').textContent).toBe("4");
});

test("increments the count", () => {
document.body.innerHTML = `<span id="count-mode-1">Valid (<span class="count">1</span>)</span>`;
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 = `<span id="count-mode-2">Pending (<span class="count">0</span>)</span>`;
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 = `<span id="count-mode-2">Pending (3)</span>`;
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();
});
});
14 changes: 7 additions & 7 deletions isso/templates/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ <h2>Administration</h2>
<div class="filters">
<div class="mode">
<a href="?mode=1&page={{page}}&order_by={{order_by}}">
<span class="label label-valid {% if mode == 1 %}active{% endif %}">
Valid ({{counts.get(1, 0)}})
<span id="count-mode-1" class="label label-valid {% if mode == 1 %}active{% endif %}">
Valid (<span class="count">{{counts.get(1, 0)}}</span>)
</span>
</a>
<a href="?mode=2&page={{page}}&order_by={{order_by}}">
<span class="label label-pending {% if mode == 2 %}active{% endif %}">
Pending ({{counts.get(2, 0)}})
<span id="count-mode-2" class="label label-pending {% if mode == 2 %}active{% endif %}">
Pending (<span class="count">{{counts.get(2, 0)}}</span>)
</span>
</a>
<a href="?mode=4&page={{page}}&order_by={{order_by}}">
<span class="label label-staled {% if mode == 4 %}active{% endif %}">
Staled ({{counts.get(4, 0)}})
<span id="count-mode-4" class="label label-staled {% if mode == 4 %}active{% endif %}">
Staled (<span class="count">{{counts.get(4, 0)}}</span>)
</span>
</a>
</div>
Expand Down Expand Up @@ -100,7 +100,7 @@ <h2>Administration</h2>
<h2 class="thread-title">{{comment.title}} (<a href="{{comment.uri}}">{{comment.uri}}</a>)</h2>
{% endif %}
{% endif %}
<div class='isso-comment' id='isso-{{comment.id}}'>
<div class='isso-comment' id='isso-{{comment.id}}' data-mode='{{comment.mode}}'>
{% if conf.avatar %}
<div class='avatar'>
svg(data-hash='#{{comment.hash}}')
Expand Down
Loading