diff --git a/app/controllers/admin.js b/app/controllers/admin.js index f64be5d..a735b15 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -57,10 +57,11 @@ class AdminController extends SiteController { } async getHomeView (req, res) { - const { link: linkService } = this.dtp.services; + const { link: linkService, dashboard: dashboardService } = this.dtp.services; res.locals.stats = { memberCount: await User.estimatedDocumentCount(), linkCount: await linkService.getTotalCount(), + userSignupHourly: await dashboardService.getUserSignupsPerHour(), }; res.render('admin/index'); } diff --git a/app/services/dashboard.js b/app/services/dashboard.js index 39f09fb..c21bd93 100644 --- a/app/services/dashboard.js +++ b/app/services/dashboard.js @@ -7,6 +7,7 @@ const mongoose = require('mongoose'); const Link = mongoose.model('Link'); +const User = mongoose.model('User'); const ResourceVisit = mongoose.model('ResourceVisit'); const moment = require('moment'); @@ -434,6 +435,51 @@ class DashboardService extends SiteService { await cacheService.setObjectEx(cacheKey, 60 * 5, response); return response; } + + async getUserSignupsPerHour ( ) { + this.log.info('generating user signup stats report'); + + const start = moment().subtract(7, 'day').toDate(); + start.setHours(0, 0, 0, 0); + + const stats = await User.aggregate([ + { + $match: { + created: { $gt: start }, + }, + }, + { + $group: { + _id: { + year: { $year: '$created' }, + month: { $month: '$created' }, + day: { $dayOfMonth: '$created' }, + hour: { $hour: '$created' }, + }, + count: { $sum: 1 }, + }, + }, + { + $project: { + _id: false, + date: { + $dateFromParts: { + year: '$_id.year', + month: '$_id.month', + day: '$_id.day', + hour: '$_id.hour', + }, + }, + count: '$count', + }, + }, + { + $sort: { date: 1 }, + }, + ]); + + return stats; + } } module.exports = { diff --git a/app/views/admin/index.pug b/app/views/admin/index.pug index 2f6bddb..87b2d9c 100644 --- a/app/views/admin/index.pug +++ b/app/views/admin/index.pug @@ -1,8 +1,20 @@ extends layouts/main block content - - div(uk-grid).uk-grid-small.uk-flex-between.uk-flex-middle + + .uk-margin + canvas(id="hourly-signups") + + div(uk-grid).uk-grid-small.uk-flex-middle .uk-width-auto +renderCell('Members', formatCount(stats.memberCount)) .uk-width-auto - +renderCell('Links', formatCount(stats.linkCount)) \ No newline at end of file + +renderCell('Links', formatCount(stats.linkCount)) + +block viewjs + script(src="/chart.js/chart.min.js") + script(src="/chartjs-adapter-moment/chartjs-adapter-moment.min.js") + script. + window.addEventListener('dtp-load', ( ) => { + const graphData = !{JSON.stringify(stats.userSignupHourly)}; + dtp.app.renderStatsGraph('#hourly-signups', 'Hourly Signups', graphData); + }); \ No newline at end of file