Skip to content

Commit

Permalink
feat: design revamp of ACP events page (#7664)
Browse files Browse the repository at this point in the history
* feat: design revamp of ACP events page

- minor UX changes
- new filter controls, filters moved to sidebar
- form usable without js
- start/end filters NOT programmed yet

* feat: events ACP limit by date and perPage

* feat: pre-fill applied filters on template render

* fix: missing translation for ACP events perPage filter

* fix: added some comments to explain setHours behaviour

* fix: stop - start + 1

* fix: socket tests

* fix: +inf, not just inf

* fix: tests, because I am an idiot
  • Loading branch information
julianlam committed Jun 4, 2019
1 parent 4b843ba commit c7f95cc
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 32 deletions.
8 changes: 7 additions & 1 deletion public/language/en-GB/admin/advanced/events.json
Expand Up @@ -2,5 +2,11 @@
"events": "Events",
"no-events": "There are no events",
"control-panel": "Events Control Panel",
"delete-events": "Delete Events"
"delete-events": "Delete Events",
"filters": "Filters",
"filters-apply": "Apply Filters",
"filter-type": "Event Type",
"filter-start": "Start Date",
"filter-end": "End Date",
"filter-perPage": "Per Page"
}
12 changes: 7 additions & 5 deletions public/less/admin/advanced/events.less
@@ -1,6 +1,8 @@
.delete-event {
i {
cursor: pointer;
margin-left: 10px;
.events-list {
.delete-event {
i {
cursor: pointer;
margin-left: 10px;
}
}
}
}
12 changes: 8 additions & 4 deletions public/src/admin/advanced/events.js
Expand Up @@ -25,10 +25,14 @@ define('admin/advanced/events', function () {
});
});

$('#filter').on('change', function () {
var filter = $(this).val();
ajaxify.go('admin/advanced/events' + (filter ? '?filter=' + filter : ''));
});
$('#apply').on('click', Events.refresh);
};

Events.refresh = function (event) {
event.preventDefault();

var formEl = $('#filters');
ajaxify.go('admin/advanced/events?' + formEl.serialize());
};

return Events;
Expand Down
20 changes: 13 additions & 7 deletions src/controllers/admin/events.js
Expand Up @@ -10,26 +10,31 @@ var eventsController = module.exports;

eventsController.get = function (req, res, next) {
var page = parseInt(req.query.page, 10) || 1;
var itemsPerPage = 20;
var itemsPerPage = parseInt(req.query.perPage, 10) || 20;
var start = (page - 1) * itemsPerPage;
var stop = start + itemsPerPage - 1;

var currentFilter = req.query.filter || '';
// Limit by date
var from = req.query.start ? new Date(req.query.start) || undefined : undefined;
var to = req.query.end ? new Date(req.query.end) || undefined : new Date();
from = from && from.setHours(0, 0, 0, 0); // setHours returns a unix timestamp (Number, not Date)
to = to && to.setHours(23, 59, 59, 999); // setHours returns a unix timestamp (Number, not Date)

var currentFilter = req.query.type || '';

async.waterfall([
function (next) {
async.parallel({
eventCount: function (next) {
db.sortedSetCard('events:time' + (currentFilter ? ':' + currentFilter : ''), next);
db.sortedSetCount('events:time' + (currentFilter ? ':' + currentFilter : ''), from || '-inf', to, next);
},
events: function (next) {
events.getEvents(currentFilter, start, stop, next);
events.getEvents(currentFilter, start, stop, from || '-inf', to, next);
},
}, next);
},
function (results) {
var types = [''].concat(events.types);
var filters = types.map(function (type) {
var types = [''].concat(events.types).map(function (type) {
return {
value: type,
name: type || 'all',
Expand All @@ -42,7 +47,8 @@ eventsController.get = function (req, res, next) {
res.render('admin/advanced/events', {
events: results.events,
pagination: pagination.create(page, pageCount, req.query),
filters: filters,
types: types,
query: req.query,
});
},
], next);
Expand Down
12 changes: 10 additions & 2 deletions src/events.js
Expand Up @@ -48,6 +48,7 @@ events.types = [
'export:uploads',
'account-locked',
'getUsersCSV',
// To add new types from plugins, just Array.push() to this array
];

/**
Expand Down Expand Up @@ -82,10 +83,17 @@ events.log = function (data, callback) {
});
};

events.getEvents = function (filter, start, stop, callback) {
events.getEvents = function (filter, start, stop, from, to, callback) {
// from/to optional
if (typeof from === 'function' && !to && !callback) {
callback = from;
from = 0;
to = Date.now();
}

async.waterfall([
function (next) {
db.getSortedSetRevRange('events:time' + (filter ? ':' + filter : ''), start, stop, next);
db.getSortedSetRevRangeByScore('events:time' + (filter ? ':' + filter : ''), start, stop - start + 1, to, from, next);
},
function (eids, next) {
db.getObjects(eids.map(eid => 'event:' + eid), next);
Expand Down
50 changes: 37 additions & 13 deletions src/views/admin/advanced/events.tpl
@@ -1,10 +1,5 @@
<div class="row events">
<div class="col-lg-9">
<select id="filter" class="form-control">
<!-- BEGIN filters -->
<option value="{filters.value}" <!-- IF filters.selected -->selected<!-- ENDIF filters.selected -->>{filters.name}</option>
<!-- END filters -->
</select>
<div class="panel panel-default">
<div class="panel-heading"><i class="fa fa-calendar-o"></i> [[admin/advanced/events:events]]</div>
<div class="panel-body">
Expand All @@ -14,19 +9,21 @@
<div class="events-list">
<!-- BEGIN events -->
<div data-eid="{events.eid}">
<span>#{events.eid} </span><span class="label label-info">{events.type}</span>
<span class="label label-default">#{events.eid}</span>
<span class="label label-info">{events.type}</span>
<span class="label label-default">uid {events.uid}</span>
<!-- IF events.ip --><span class="label label-default">{events.ip}</span><!-- END -->
<a href="{config.relative_path}/user/{events.user.userslug}" target="_blank">
<!-- IF events.user.picture -->
<img class="avatar avatar-sm" src="{events.user.picture}" />
<img class="avatar avatar-xs" src="{events.user.picture}" />
<!-- ELSE -->
<div class="avatar avatar-sm" style="background-color: {events.user.icon:bgColor};">{events.user.icon:text}</div>
<div class="avatar avatar-xs" style="background-color: {events.user.icon:bgColor};">{events.user.icon:text}</div>
<!-- ENDIF events.user.picture -->
</a>
<a href="{config.relative_path}/user/{events.user.userslug}" target="_blank">{events.user.username}</a> (uid {events.uid}) (IP {events.ip})
<a href="{config.relative_path}/user/{events.user.userslug}" target="_blank">{events.user.username}</a>
<span class="pull-right delete-event"><i class="fa fa-trash-o"></i></span>
<span class="pull-right">{events.timestampISO}</span>
<br /><br />
<pre>{events.jsonString}</pre>
<pre class="well">{events.jsonString}</pre>
</div>
<!-- END events -->
<!-- IMPORT partials/paginator.tpl -->
Expand All @@ -36,9 +33,36 @@
</div>
<div class="col-lg-3 acp-sidebar">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-heading">[[admin/advanced/events:filters]]</div>
<div class="panel-body">
<button class="btn btn-warning" data-action="clear">
<form role="form" id="filters">
<div class="form-group">
<label for="type">[[admin/advanced/events:filter-type]]</label>
<select class="form-control" id="type" name="type" class="form-control">
<!-- BEGIN types -->
<option value="{types.value}" <!-- IF types.selected -->selected<!-- ENDIF types.selected -->>{types.name}</option>
<!-- END types -->
</select>
</div>
<div class="form-group">
<label for="start">[[admin/advanced/events:filter-start]]</label>
<input type="date" id="start" name="start" value="{query.start}" class="form-control" />
</div>
<div class="form-group">
<label for="end">[[admin/advanced/events:filter-end]]</label>
<input type="date" id="end" name="end" value="{query.end}" class="form-control" />
</div>
<div class="form-group">
<label for="perPage">[[admin/advanced/events:filter-perPage]]</label>
<input type="text" id="perPage" name="perPage" value="{query.perPage}" class="form-control" />
</div>
<button type="submit" class="btn btn-primary btn-block" id="apply">[[admin/advanced/events:filters-apply]]</button>
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<button class="btn btn-block btn-danger" data-action="clear">
<i class="fa fa-eraser"></i> [[admin/advanced/events:delete-events]]
</button>
</div>
Expand Down

0 comments on commit c7f95cc

Please sign in to comment.