Add a support inbox icon to the topbar (sow-nodebb-plugin-support#10)
Mirrors the existing unread-drawer pattern: a new dropdown next to the notification bell, gated on templateData.support.visible (injected by the support plugin's filter:middleware.renderHeader hook, on every page render, for viewers with any support access at all). Opening it fetches GET /plugins/support/notifications via the api module, renders up to 10 entries by textContent (never innerHTML), and marks everything read via POST .../notifications/read, clearing the badge client-side. Also present in the mobile burger drawer, same gating. ponytail: no live socket push for this badge (core's own unread/notification counts get one); it only catches up on the next full page load after the box is opened. Noted in client.js as the upgrade path if that gap matters. Verified live against sow-nodebb-plugin-support's dev NodeBB stack (theme + plugin both mounted): icon hidden for a user with no support access, badge count and dropdown contents correct for a reviewer, badge clears on open. Full plain-node test suite passes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -208,6 +208,59 @@
|
||||
});
|
||||
}
|
||||
|
||||
function clearSupportBadge() {
|
||||
toArray(document.querySelectorAll('[component="support/count"]')).forEach((badge) => {
|
||||
badge.textContent = '0';
|
||||
badge.classList.add('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
function renderSupportMenu(menuEl, entries) {
|
||||
if (!menuEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const relativePath = (window.config && window.config.relative_path) || '';
|
||||
|
||||
// remove the loading row and any previously injected entries; the
|
||||
// empty-state and footer/divider rows are server-rendered and stay put
|
||||
const loading = menuEl.querySelector('[data-wg-support-loading]');
|
||||
if (loading) {
|
||||
loading.remove();
|
||||
}
|
||||
toArray(menuEl.querySelectorAll('.wg-support-item')).forEach((li) => {
|
||||
li.remove();
|
||||
});
|
||||
|
||||
const emptyEl = menuEl.querySelector('[data-wg-support-empty]');
|
||||
const footerEl = menuEl.querySelector('[data-wg-support-footer]');
|
||||
|
||||
const list = (entries || []).slice(0, 10);
|
||||
if (emptyEl) {
|
||||
emptyEl.classList.toggle('hidden', list.length > 0);
|
||||
}
|
||||
|
||||
list.forEach((entry) => {
|
||||
const link = document.createElement('a');
|
||||
link.className = 'dropdown-item wg-support-item text-truncate';
|
||||
link.href = relativePath + entry.path;
|
||||
link.textContent = entry.bodyShort;
|
||||
if (!entry.read) {
|
||||
link.classList.add('wg-support-item--unread');
|
||||
}
|
||||
|
||||
const li = document.createElement('li');
|
||||
li.className = 'wg-support-item';
|
||||
li.appendChild(link);
|
||||
|
||||
if (footerEl) {
|
||||
menuEl.insertBefore(li, footerEl);
|
||||
} else {
|
||||
menuEl.appendChild(li);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getWestgateTopbar() {
|
||||
if (!document || typeof document.querySelector !== 'function') {
|
||||
return null;
|
||||
@@ -293,12 +346,36 @@
|
||||
renderUnreadMenu(menuEl, []);
|
||||
});
|
||||
});
|
||||
|
||||
$(document)
|
||||
.off('show.bs.dropdown.westgateSupport')
|
||||
.on('show.bs.dropdown.westgateSupport', '.wg-topbar [component="support"]', function () {
|
||||
const menuEl = this.querySelector('[data-wg-support-menu]');
|
||||
require(['api'], function (api) {
|
||||
api.get('/plugins/support/notifications', {}, function (err, data) {
|
||||
if (err) {
|
||||
renderSupportMenu(menuEl, []);
|
||||
return;
|
||||
}
|
||||
renderSupportMenu(menuEl, data && data.notifications);
|
||||
// ponytail: unlike core's unread/notification badges, this one
|
||||
// gets no live socket push, so it only catches up on the next
|
||||
// full page load after the box is opened here. Add a socket
|
||||
// event if that gap matters.
|
||||
if (data && data.unreadCount) {
|
||||
api.post('/plugins/support/notifications/read', {}, function () {});
|
||||
clearSupportBadge();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.westgateTheme = window.westgateTheme || {};
|
||||
window.westgateTheme.wrapWikiTables = wrapWestgateWikiTables;
|
||||
window.westgateTheme.initTopbar = initWestgateTopbar;
|
||||
window.westgateTheme.renderUnreadMenu = renderUnreadMenu;
|
||||
window.westgateTheme.renderSupportMenu = renderSupportMenu;
|
||||
|
||||
$(document).ready(function () {
|
||||
wrapWestgateWikiTables(document);
|
||||
|
||||
Reference in New Issue
Block a user