From f2df1aea4b86de0535a009178e3aec0fbdd8a89c Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Thu, 24 Sep 2020 09:32:15 +0000 Subject: [PATCH] Global manage page for boards. Shows all boards including unlisted, and marks abandoned boards --- controllers/pages.js | 3 +- db/boards.js | 30 ++++++----- gulp/res/js/localstorage.js | 2 +- models/pages/boardlist.js | 14 ++--- models/pages/globalmanage/boards.js | 76 +++++++++++++++++++++++++++ models/pages/globalmanage/index.js | 1 + views/mixins/globalmanagenav.pug | 2 + views/pages/boardlist.pug | 4 +- views/pages/globalmanageboardlist.pug | 57 ++++++++++++++++++++ 9 files changed, 162 insertions(+), 27 deletions(-) create mode 100644 models/pages/globalmanage/boards.js create mode 100644 views/pages/globalmanageboardlist.pug diff --git a/controllers/pages.js b/controllers/pages.js index 47746f29..3b73c6e7 100644 --- a/controllers/pages.js +++ b/controllers/pages.js @@ -19,7 +19,7 @@ const express = require('express') //page models , { manageRecent, manageReports, manageBanners, manageSettings, manageBans, manageBoard, manageThread, manageLogs, manageCatalog } = require(__dirname+'/../models/pages/manage/') - , { globalManageSettings, globalManageReports, globalManageBans, + , { globalManageSettings, globalManageReports, globalManageBans, globalManageBoards, globalManageRecent, globalManageAccounts, globalManageNews, globalManageLogs } = require(__dirname+'/../models/pages/globalmanage/') , { changePassword, blockBypass, home, register, login, create, board, catalog, banners, randombanner, news, captchaPage, overboard, @@ -61,6 +61,7 @@ router.get('/:board/manage/thread/:id([1-9][0-9]{0,}).html', useSession, session router.get('/globalmanage/reports.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageReports); router.get('/globalmanage/bans.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageBans); router.get('/globalmanage/recent.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageRecent); +router.get('/globalmanage/boards.(html|json)', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), globalManageBoards); router.get('/globalmanage/globallogs.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageLogs); router.get('/globalmanage/news.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageNews); router.get('/globalmanage/accounts.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageAccounts); diff --git a/db/boards.js b/db/boards.js index 3f16bb86..cc7f7062 100644 --- a/db/boards.js +++ b/db/boards.js @@ -150,8 +150,23 @@ module.exports = { boardSort: (skip=0, limit=50, sort={ ips:-1, pph:-1, sequence_value:-1 }, filter={}, showUnlisted=false) => { const addedFilter = {}; + const projection = { + '_id': 1, + 'lastPostTimestamp': 1, + 'sequence_value': 1, + 'pph': 1, + 'ips': 1, + 'settings.sfw': 1, + 'settings.description': 1, + 'settings.name': 1, + 'settings.tags': 1, + 'settings.unlistedLocal': 1, + }; if (!showUnlisted) { addedFilter['settings.unlistedLocal'] = false; + } else { + projection['settings.moderators'] = 1; + projection['owner'] = 1; } if (filter.search) { addedFilter['$or'] = [ @@ -159,20 +174,7 @@ module.exports = { { '_id': filter.search }, ]; } - return db.find(addedFilter, { - 'projection': { - '_id': 1, - 'lastPostTimestamp': 1, - 'sequence_value': 1, - 'pph': 1, - 'ips': 1, - 'settings.sfw': 1, - 'settings.description': 1, - 'settings.name': 1, - 'settings.tags': 1, - 'settings.unlistedLocal': 1, - } - }) + return db.find(addedFilter, { projection }) .sort(sort) .skip(skip) .limit(limit) diff --git a/gulp/res/js/localstorage.js b/gulp/res/js/localstorage.js index 386410c0..07305b44 100644 --- a/gulp/res/js/localstorage.js +++ b/gulp/res/js/localstorage.js @@ -1,7 +1,7 @@ const isCatalog = window.location.pathname.endsWith('catalog.html'); const isThread = /\/\w+\/thread\/\d+.html/.test(window.location.pathname); const isModView = /\/\w+\/manage\/(thread\/)?(index|\d+).html/.test(window.location.pathname); -const isManage = /\/(\w+\/manage|globalmanage)\/(recent|reports|bans|logs|settings|banners|accounts|news).html/.test(window.location.pathname); +const isManage = /\/(\w+\/manage|globalmanage)\/(recent|reports|bans|boards|logs|settings|banners|accounts|news).html/.test(window.location.pathname); function setLocalStorage(key, value) { try { diff --git a/models/pages/boardlist.js b/models/pages/boardlist.js index 8d84f760..f1d8beda 100644 --- a/models/pages/boardlist.js +++ b/models/pages/boardlist.js @@ -9,7 +9,6 @@ const { enableWebring } = require(__dirname+'/../../configs/main.js') module.exports = async (req, res, next) => { - const isGlobalStaff = res.locals.permLevel <= 1; const { page, offset, queryString } = pageQueryConverter(req.query, limit); const direction = req.query.direction && req.query.direction === 'asc' ? 1 : -1; const search = (typeof req.query.search === 'string' ? req.query.search : null); @@ -45,9 +44,9 @@ module.exports = async (req, res, next) => { try { [ localBoards, localPages, webringBoards, webringPages ] = await Promise.all([ - Boards.boardSort(offset, limit, sort, filter, isGlobalStaff), - Boards.count(filter, isGlobalStaff), - enableWebring ? Webring.boardSort(offset, limit, sort, filter, isGlobalStaff) : null, + Boards.boardSort(offset, limit, sort, filter), + Boards.count(filter), + enableWebring ? Webring.boardSort(offset, limit, sort, filter) : null, enableWebring ? Webring.count(filter) : 0, ]); localPages = Math.ceil(localPages / limit); @@ -56,10 +55,7 @@ module.exports = async (req, res, next) => { } catch (err) { return next(err); } - - if (!isGlobalStaff) { - cache.set(`boardlist:${cacheQueryString}`, { localBoards, localPages, webringBoards, webringPages, maxPage }, 60); - } + cache.set(`boardlist:${cacheQueryString}`, { localBoards, localPages, webringBoards, webringPages, maxPage }, 60); } const now = new Date(); @@ -87,7 +83,7 @@ module.exports = async (req, res, next) => { } res - .set('Cache-Control', `${isGlobalStaff ? 'private' : 'public'}, max-age=60`); + .set('Cache-Control', 'public, max-age=60'); if (req.path === '/boards.json') { res.json({ diff --git a/models/pages/globalmanage/boards.js b/models/pages/globalmanage/boards.js new file mode 100644 index 00000000..4b6d39fc --- /dev/null +++ b/models/pages/globalmanage/boards.js @@ -0,0 +1,76 @@ +'use strict'; + +const { Boards } = require(__dirname+'/../../../db/') + , { relativeColor, relativeString } = require(__dirname+'/../../../helpers/timeutils.js') + , pageQueryConverter = require(__dirname+'/../../../helpers/pagequeryconverter.js') + , limit = 20; + +module.exports = async (req, res, next) => { + + const { page, offset, queryString } = pageQueryConverter(req.query, limit); + const direction = req.query.direction && req.query.direction === 'asc' ? 1 : -1; + const search = (typeof req.query.search === 'string' ? req.query.search : null); + let sort = req.query.sort && req.query.sort === 'activity' ? 'activity' : 'popularity'; + + if (sort === 'activity') { + sort = { + 'lastPostTimestamp': direction + } + } else { + sort = { + 'ips': direction, + 'pph': direction, + 'sequence_value': direction + }; + } + + let filter = {}; + if (req.query.search && search) { + filter = { + 'search': search + } + } + + let localBoards, pages, maxPage; + try { + [ localBoards, pages ] = await Promise.all([ + Boards.boardSort(offset, limit, sort, filter, true), + Boards.count(filter, true), + ]); + maxPage = Math.ceil(pages / limit); + } catch (err) { + return next(err); + } + + const now = new Date(); + if (localBoards) { + for (let i = 0; i < localBoards.length; i++) { + if (localBoards[i].lastPostTimestamp) { + const lastPostDate = new Date(localBoards[i].lastPostTimestamp); + localBoards[i].lastPostTimestamp = { + text: relativeString(now, lastPostDate), + color: relativeColor(now, lastPostDate) + } + } + } + } + res.set('Cache-Control', 'private, max-age=60'); + + if (req.path.endsWith('/boards.json')) { + res.json({ + localBoards, + page, + maxPage, + }); + } else { + res.render('globalmanageboardlist', { + localBoards, + page, + maxPage, + query: req.query, + search, + queryString, + }); + } + +} diff --git a/models/pages/globalmanage/index.js b/models/pages/globalmanage/index.js index 8ea2784b..02cc8a84 100644 --- a/models/pages/globalmanage/index.js +++ b/models/pages/globalmanage/index.js @@ -4,6 +4,7 @@ module.exports = { globalManageReports: require(__dirname+'/reports.js'), globalManageBans: require(__dirname+'/bans.js'), globalManageLogs: require(__dirname+'/logs.js'), + globalManageBoards: require(__dirname+'/boards.js'), globalManageRecent: require(__dirname+'/recent.js'), globalManageNews: require(__dirname+'/news.js'), globalManageAccounts: require(__dirname+'/accounts.js'), diff --git a/views/mixins/globalmanagenav.pug b/views/mixins/globalmanagenav.pug index 5223c1ba..9de4a50a 100644 --- a/views/mixins/globalmanagenav.pug +++ b/views/mixins/globalmanagenav.pug @@ -6,6 +6,8 @@ mixin globalmanagenav(selected) | a(href='recent.html' class=(selected === 'recent' ? 'bold' : '')) [Recent] | + a(href='boards.html' class=(selected === 'boards' ? 'bold' : '')) [Boards] + | a(href='globallogs.html' class=(selected === 'logs' ? 'bold' : '')) [Logs] if permLevel === 0 | diff --git a/views/pages/boardlist.pug b/views/pages/boardlist.pug index e859817c..a726a7be 100644 --- a/views/pages/boardlist.pug +++ b/views/pages/boardlist.pug @@ -9,7 +9,7 @@ block content | or try the a(href='/all.html') overboard .flexcenter.mv-10 - form.form-post(action=`/boards.html` method='GET') + form.form-post(action='/boards.html' method='GET') input(type='hidden' value=page) .row .label Search @@ -36,7 +36,7 @@ block content span.help(title='SFW') 💼 | if board.settings.unlistedLocal === true - span(title='Unlisted') 👁️ + span.help(title='Unlisted') 👁️ | a(href=`/${board._id}/index.html`) /#{board._id}/ - #{board.settings.name} td #{board.settings.description} diff --git a/views/pages/globalmanageboardlist.pug b/views/pages/globalmanageboardlist.pug new file mode 100644 index 00000000..0e36b9aa --- /dev/null +++ b/views/pages/globalmanageboardlist.pug @@ -0,0 +1,57 @@ +extends ../layout.pug +include ../mixins/ban.pug +include ../mixins/globalmanagenav.pug + +block head + title Manage + +block content + h1.board-title Global Management + br + +globalmanagenav('boards') + hr(size=1) + h4.text-center.no-m-p Filter: + .flexcenter.mv-10 + form.form-post(action='/globalmanage/boards.html' method='GET') + input(type='hidden' value=page) + .row + .label Search + input(type='text' name='search' value=search placeholder='Uri or tags') + .row + .label Sort + select(name='sort') + option(value='popularity') Popularity + option(value='activity' selected=query.sort === 'activity') Latest Activity + .row + .label Order + select(name='direction') + option(value='desc') Descending + option(value='asc' selected=query.direction === 'asc') Ascending + input(type='submit', value='Filter') + if localBoards && localBoards.length > 0 + h4.text-center.mv-10 Board List: + include ../includes/webringboardtable.pug + each board in localBoards + tr + td + span.left + if board.settings.sfw === true + span.help(title='SFW') 💼 + | + if board.settings.unlistedLocal === true + span.help(title='Unlisted') 👁️ + | + if !board.owner && board.settings.moderators.length === 0 + span.help(title='Abandoned') 🏚️ + | + a(href=`/${board._id}/index.html`) /#{board._id}/ - #{board.settings.name} + td #{board.settings.description} + td #{board.pph} + td #{board.ips} + td #{board.sequence_value-1} + if board.lastPostTimestamp + td(style=`background-color: ${board.lastPostTimestamp.color}`) #{board.lastPostTimestamp.text} + else + td - + .pages.text-center.mt-5.mv-0 + include ../includes/pages.pug