mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
feat: search dashboard time range
This commit is contained in:
@@ -83,8 +83,11 @@
|
||||
"back-to-dashboard": "Back to Dashboard",
|
||||
"details.no-users": "No users have joined within the selected timeframe",
|
||||
"details.no-topics": "No topics have been posted within the selected timeframe",
|
||||
"details.no-searches": "No searches have been made yet",
|
||||
"details.no-searches": "No searches have been made within the selected timeframe",
|
||||
"details.no-logins": "No logins have been recorded within the selected timeframe",
|
||||
"details.logins-static": "NodeBB only saves session data for %1 days, and so this table below will only show the most recently active sessions",
|
||||
"details.logins-login-time": "Login Time"
|
||||
"details.logins-login-time": "Login Time",
|
||||
"start": "Start",
|
||||
"end": "End",
|
||||
"filter": "Filter"
|
||||
}
|
||||
|
||||
@@ -337,8 +337,54 @@ dashboardController.getTopics = async (req, res) => {
|
||||
};
|
||||
|
||||
dashboardController.getSearches = async (req, res) => {
|
||||
const searches = await db.getSortedSetRevRangeWithScores('searches:all', 0, 99);
|
||||
let start = 0;
|
||||
let end = 0;
|
||||
if (req.query.start) {
|
||||
start = new Date(req.query.start);
|
||||
start.setHours(24, 0, 0, 0);
|
||||
end = new Date();
|
||||
end.setHours(24, 0, 0, 0);
|
||||
}
|
||||
if (req.query.end) {
|
||||
end = new Date(req.query.end);
|
||||
end.setHours(24, 0, 0, 0);
|
||||
}
|
||||
|
||||
let searches;
|
||||
if (start && end && start <= end) {
|
||||
const daysArr = [start];
|
||||
const nextDay = new Date(start.getTime());
|
||||
while (nextDay < end) {
|
||||
nextDay.setDate(nextDay.getDate() + 1);
|
||||
nextDay.setHours(0, 0, 0, 0);
|
||||
daysArr.push(new Date(nextDay.getTime()));
|
||||
}
|
||||
|
||||
const daysData = await Promise.all(
|
||||
daysArr.map(async d => db.getSortedSetRevRangeWithScores(`searches:${d.getTime()}`, 0, -1))
|
||||
);
|
||||
|
||||
const map = {};
|
||||
daysData.forEach((d) => {
|
||||
d.forEach((search) => {
|
||||
if (!map[search.value]) {
|
||||
map[search.value] = search.score;
|
||||
} else {
|
||||
map[search.value] += search.score;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
searches = Object.keys(map)
|
||||
.map(key => ({ value: key, score: map[key] }))
|
||||
.sort((a, b) => b.score - a.score);
|
||||
} else {
|
||||
searches = await db.getSortedSetRevRangeWithScores('searches:all', 0, 99);
|
||||
}
|
||||
|
||||
res.render('admin/dashboard/searches', {
|
||||
searches: searches.map(s => ({ value: validator.escape(String(s.value)), score: s.score })),
|
||||
startDate: validator.escape(String(req.query.start)),
|
||||
endDate: validator.escape(String(req.query.end)),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
'use strict';
|
||||
|
||||
const validator = require('validator');
|
||||
const _ = require('lodash');
|
||||
|
||||
const db = require('../database');
|
||||
const meta = require('../meta');
|
||||
@@ -120,7 +121,12 @@ async function recordSearch(data) {
|
||||
q => !copy.find(query => query.startsWith(q) && query.length > q.length)
|
||||
);
|
||||
delete searches[data.uid];
|
||||
await Promise.all(filtered.map(query => db.sortedSetIncrBy('searches:all', 1, query)));
|
||||
const dayTimestamp = (new Date());
|
||||
dayTimestamp.setHours(0, 0, 0, 0);
|
||||
await Promise.all(_.uniq(filtered).map(async (query) => {
|
||||
await db.sortedSetIncrBy('searches:all', 1, query);
|
||||
await db.sortedSetIncrBy(`searches:${dayTimestamp.getTime()}`, 1, query);
|
||||
}));
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
<div class="row dashboard">
|
||||
<div class="col-xs-12">
|
||||
<a class="btn btn-link" href="{config.relative_path}/admin/dashboard">
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
[[admin/dashboard:back-to-dashboard]]
|
||||
</a>
|
||||
|
||||
<div class="clearfix">
|
||||
<a class="btn btn-link" href="{config.relative_path}/admin/dashboard">
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
[[admin/dashboard:back-to-dashboard]]
|
||||
</a>
|
||||
<form class="form-inline pull-right" method="GET">
|
||||
<div class="form-group">
|
||||
<label>[[admin/dashboard:start]]</label>
|
||||
<input type="date" class="form-control" name="start" value="{startDate}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>[[admin/dashboard:end]]</label>
|
||||
<input type="date" class="form-control" name="end" value="{endDate}">
|
||||
</div>
|
||||
<button onclick="$('form').submit();return false;"class="btn btn-primary" type="submit">Filter</button>
|
||||
</form>
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
<table class="table table-striped search-list">
|
||||
<tbody>
|
||||
|
||||
Reference in New Issue
Block a user