feat: load unread topics into topbar drawer on open
This commit is contained in:
@@ -159,6 +159,61 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderUnreadMenu(menuEl, topics) {
|
||||||
|
if (!menuEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuEl.textContent = '';
|
||||||
|
const relativePath = (window.config && window.config.relative_path) || '';
|
||||||
|
|
||||||
|
function addItem(node) {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.appendChild(node);
|
||||||
|
menuEl.appendChild(li);
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = (topics || []).slice(0, 10);
|
||||||
|
if (!list.length) {
|
||||||
|
const empty = document.createElement('span');
|
||||||
|
empty.className = 'dropdown-item disabled';
|
||||||
|
empty.textContent = '[[unread:no-unread-topics]]';
|
||||||
|
addItem(empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.forEach((topic) => {
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.className = 'dropdown-item wg-unread-item text-truncate';
|
||||||
|
link.href = `${relativePath}/topic/${topic.slug}`;
|
||||||
|
link.textContent = topic.title;
|
||||||
|
if (topic.category && topic.category.name) {
|
||||||
|
const category = document.createElement('small');
|
||||||
|
category.className = 'wg-unread-item__category';
|
||||||
|
category.textContent = topic.category.name;
|
||||||
|
link.appendChild(category);
|
||||||
|
}
|
||||||
|
addItem(link);
|
||||||
|
});
|
||||||
|
|
||||||
|
const divider = document.createElement('hr');
|
||||||
|
divider.className = 'dropdown-divider';
|
||||||
|
addItem(divider);
|
||||||
|
|
||||||
|
const seeAll = document.createElement('a');
|
||||||
|
seeAll.className = 'dropdown-item wg-unread-item--all';
|
||||||
|
seeAll.href = `${relativePath}/unread`;
|
||||||
|
seeAll.textContent = '[[unread:title]]';
|
||||||
|
addItem(seeAll);
|
||||||
|
|
||||||
|
if (window.require) {
|
||||||
|
window.require(['translator'], function (translator) {
|
||||||
|
translator.translate(menuEl.innerHTML, (translated) => {
|
||||||
|
menuEl.innerHTML = translated;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getWestgateTopbar() {
|
function getWestgateTopbar() {
|
||||||
if (!document || typeof document.querySelector !== 'function') {
|
if (!document || typeof document.querySelector !== 'function') {
|
||||||
return null;
|
return null;
|
||||||
@@ -225,11 +280,27 @@
|
|||||||
.on('shown.bs.dropdown.westgateTopbar', '.wg-topbar [component="sidebar/search"]', function () {
|
.on('shown.bs.dropdown.westgateTopbar', '.wg-topbar [component="sidebar/search"]', function () {
|
||||||
$(this).find('[component="search/fields"] input[name="query"]').trigger('focus');
|
$(this).find('[component="search/fields"] input[name="query"]').trigger('focus');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off('show.bs.dropdown.westgateUnread')
|
||||||
|
.on('show.bs.dropdown.westgateUnread', '.wg-topbar [component="unread"]', function () {
|
||||||
|
const menuEl = this.querySelector('[data-wg-unread-menu]');
|
||||||
|
require(['api'], function (api) {
|
||||||
|
api.get('/unread', {}, function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
renderUnreadMenu(menuEl, []);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
renderUnreadMenu(menuEl, data && data.topics);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.westgateTheme = window.westgateTheme || {};
|
window.westgateTheme = window.westgateTheme || {};
|
||||||
window.westgateTheme.wrapWikiTables = wrapWestgateWikiTables;
|
window.westgateTheme.wrapWikiTables = wrapWestgateWikiTables;
|
||||||
window.westgateTheme.initTopbar = initWestgateTopbar;
|
window.westgateTheme.initTopbar = initWestgateTopbar;
|
||||||
|
window.westgateTheme.renderUnreadMenu = renderUnreadMenu;
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
wrapWestgateWikiTables(document);
|
wrapWestgateWikiTables(document);
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const client = fs.readFileSync(path.join(__dirname, '..', 'public', 'client.js'), 'utf8');
|
||||||
|
|
||||||
|
assert(
|
||||||
|
client.includes("'show.bs.dropdown.westgateUnread'"),
|
||||||
|
'client.js should fetch unread topics when the unread dropdown opens'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
client.includes("api.get('/unread'"),
|
||||||
|
'client.js should load the unread list from the /unread API'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
client.includes('renderUnreadMenu'),
|
||||||
|
'client.js should expose the unread menu renderer'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
/textContent/.test(client) && !/innerHTML\s*=[^=]*title/.test(client),
|
||||||
|
'Topic titles must be inserted via textContent, never innerHTML'
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user