|
| 1 | + |
| 2 | +'use strict'; |
| 3 | + |
| 4 | +const querystring = require('querystring'); |
| 5 | + |
| 6 | +const _ = require.main.require('lodash'); |
| 7 | + |
| 8 | +const db = require.main.require('./src/database'); |
| 9 | +const routeHelpers = require.main.require('./src/routes/helpers'); |
| 10 | +const controllerHelpers = require.main.require('./src/controllers/helpers'); |
| 11 | +const topics = require.main.require('./src/topics'); |
| 12 | +const groups = require.main.require('./src/groups'); |
| 13 | +const posts = require.main.require('./src/posts'); |
| 14 | +const privileges = require.main.require('./src/privileges'); |
| 15 | +const pagination = require.main.require('./src/pagination'); |
| 16 | +const meta = require.main.require('./src/meta'); |
| 17 | + |
| 18 | +const devTracker = module.exports; |
| 19 | + |
| 20 | +devTracker.init = async function (params) { |
| 21 | + routeHelpers.setupPageRoute(params.router, '/dev-tracker', renderDevTracker); |
| 22 | + routeHelpers.setupAdminPageRoute(params.router, '/admin/plugins/dev-tracker', renderAdmin); |
| 23 | +}; |
| 24 | + |
| 25 | +async function renderAdmin(req, res) { |
| 26 | + const groupsData = await groups.getNonPrivilegeGroups('groups:createtime', 0, -1); |
| 27 | + groupsData.sort((a, b) => b.system - a.system); |
| 28 | + res.render('admin/plugins/dev-tracker', { groups: groupsData }); |
| 29 | +} |
| 30 | + |
| 31 | +async function getDevTrackerGroups() { |
| 32 | + const settings = await meta.settings.get('dev-tracker'); |
| 33 | + let groups = settings.devTrackerGroups || '[]'; |
| 34 | + try { |
| 35 | + groups = JSON.parse(groups); |
| 36 | + return groups; |
| 37 | + } catch (err) { |
| 38 | + console.error(err.stack); |
| 39 | + return []; |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +async function getDevTrackerUidsFromGroups(groupNames) { |
| 44 | + const arrayOfUids = await groups.getMembersOfGroups(groupNames); |
| 45 | + return _.uniq(_.flatten(arrayOfUids)); |
| 46 | +} |
| 47 | + |
| 48 | +async function renderDevTracker(req, res) { |
| 49 | + const page = Math.max(1, parseInt(req.query.page, 10) || 1); |
| 50 | + const cids = getCidsArray(req.query.cid); |
| 51 | + const groupNames = await getDevTrackerGroups(); |
| 52 | + const currentGroup = req.query.group || ''; |
| 53 | + let showPosts = parseInt(req.query.posts, 10) === 1; |
| 54 | + const showTopics = parseInt(req.query.topics, 10) === 1; |
| 55 | + if (!showPosts && !showTopics) { |
| 56 | + showPosts = true; |
| 57 | + } |
| 58 | + |
| 59 | + const [uids, groupData, categoryData] = await Promise.all([ |
| 60 | + getDevTrackerUidsFromGroups(currentGroup ? [currentGroup] : groupNames), |
| 61 | + groups.getGroupsData(groupNames), |
| 62 | + controllerHelpers.getSelectedCategory(cids), |
| 63 | + ]); |
| 64 | + |
| 65 | + groupData.forEach((group) => { |
| 66 | + group.selected = group.name === req.query.group; |
| 67 | + group.url = `dev-tracker?${querystring.stringify({ ...req.query, group: group.name })}`; |
| 68 | + }); |
| 69 | + let data = []; |
| 70 | + if (showPosts) { |
| 71 | + data = await getPosts(req, uids, cids); |
| 72 | + } else if (showTopics) { |
| 73 | + data = await getTopics(req, uids, cids); |
| 74 | + } |
| 75 | + |
| 76 | + delete req.query._; |
| 77 | + res.render('dev-tracker', { |
| 78 | + showPosts, |
| 79 | + showTopics, |
| 80 | + posts: data.posts, |
| 81 | + topics: data.topics, |
| 82 | + groups: groupData, |
| 83 | + allCategoriesUrl: `dev-tracker${controllerHelpers.buildQueryString(req.query, 'cid', '')}`, |
| 84 | + allGroupsUrl: `dev-tracker${controllerHelpers.buildQueryString(req.query, 'group', '')}`, |
| 85 | + selectedGroup: groupData.find(g => g.name === req.query.group), |
| 86 | + selectedCategory: categoryData.selectedCategory, |
| 87 | + selectedCids: categoryData.selectedCids, |
| 88 | + pagination: pagination.create(page, data.pageCount, req.query), |
| 89 | + }); |
| 90 | +} |
| 91 | + |
| 92 | +async function getPosts(req, uids, cids) { |
| 93 | + const sets = _.flatten(uids.map((uid) => { |
| 94 | + if (cids) { |
| 95 | + return cids.map(cid => `cid:${cid}:uid:${uid}:pids`); |
| 96 | + } |
| 97 | + return `uid:${uid}:posts`; |
| 98 | + })); |
| 99 | + const allPids = await db.getSortedSetRevRange(sets, 0, 499); |
| 100 | + const pids = await privileges.posts.filter('topics:read', allPids, req.uid); |
| 101 | + |
| 102 | + const pageCount = Math.max(1, Math.ceil(pids.length / meta.config.postsPerPage)); |
| 103 | + const page = Math.max(1, parseInt(req.query.page, 10) || 1); |
| 104 | + |
| 105 | + const start = Math.max(0, (page - 1) * meta.config.postsPerPage); |
| 106 | + const stop = start + meta.config.postsPerPage - 1; |
| 107 | + const pagePids = page > pageCount ? [] : pids.slice(start, stop + 1); |
| 108 | + const postData = await posts.getPostSummaryByPids(pagePids, req.uid, { stripTags: false }); |
| 109 | + return { |
| 110 | + posts: postData, |
| 111 | + pageCount, |
| 112 | + }; |
| 113 | +} |
| 114 | + |
| 115 | +async function getTopics(req, uids, cids) { |
| 116 | + const sets = _.flatten(uids.map((uid) => { |
| 117 | + if (cids) { |
| 118 | + return cids.map(cid => `cid:${cid}:uid:${uid}:tids`); |
| 119 | + } |
| 120 | + return `uid:${uid}:topics`; |
| 121 | + })); |
| 122 | + const allTids = await db.getSortedSetRevRange(sets, 0, 499); |
| 123 | + const tids = await privileges.topics.filterTids('topics:read', allTids, req.uid); |
| 124 | + |
| 125 | + const pageCount = Math.max(1, Math.ceil(tids.length / meta.config.topicsPerPage)); |
| 126 | + const page = Math.max(1, parseInt(req.query.page, 10) || 1); |
| 127 | + |
| 128 | + const start = Math.max(0, (page - 1) * meta.config.topicsPerPage); |
| 129 | + const stop = start + meta.config.topicsPerPage - 1; |
| 130 | + const pageTids = page > pageCount ? [] : tids.slice(start, stop + 1); |
| 131 | + const topicData = await topics.getTopicsByTids(pageTids, req.uid); |
| 132 | + topics.calculateTopicIndices(topicData, start); |
| 133 | + return { |
| 134 | + topics: topicData, |
| 135 | + pageCount, |
| 136 | + }; |
| 137 | +} |
| 138 | + |
| 139 | +function getCidsArray(cid) { |
| 140 | + if (cid && !Array.isArray(cid)) { |
| 141 | + cid = [cid]; |
| 142 | + } |
| 143 | + return cid && cid.map(cid => parseInt(cid, 10)); |
| 144 | +} |
| 145 | + |
| 146 | +devTracker.addAdminNavigation = function (header) { |
| 147 | + header.plugins.push({ |
| 148 | + route: '/plugins/dev-tracker', |
| 149 | + icon: 'fa-list', |
| 150 | + name: 'Dev Tracker', |
| 151 | + }); |
| 152 | + return header; |
| 153 | +}; |
| 154 | + |
| 155 | +devTracker.defineWidgetAreas = async function (areas) { |
| 156 | + areas = areas.concat([ |
| 157 | + { |
| 158 | + name: 'Dev Tracker Page (Header)', |
| 159 | + template: 'dev-tracker.tpl', |
| 160 | + location: 'header', |
| 161 | + }, |
| 162 | + { |
| 163 | + name: 'Dev Tracker Page (Left)', |
| 164 | + template: 'dev-tracker.tpl', |
| 165 | + location: 'left', |
| 166 | + }, |
| 167 | + { |
| 168 | + name: 'Dev Tracker Page (Right)', |
| 169 | + template: 'dev-tracker.tpl', |
| 170 | + location: 'right', |
| 171 | + }, |
| 172 | + { |
| 173 | + name: 'Dev Tracker Page (Footer)', |
| 174 | + template: 'dev-tracker.tpl', |
| 175 | + location: 'footer', |
| 176 | + }, |
| 177 | + ]); |
| 178 | + return areas; |
| 179 | +}; |
0 commit comments