2017-12-10 21:11:13 +10:30
|
|
|
var Chart=function(){"use strict";function t(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function e(t){var e=t.getBoundingClientRect();return{top:e.top+(document.documentElement.scrollTop||document.body.scrollTop),left:e.left+(document.documentElement.scrollLeft||document.body.scrollLeft)}}function i(t){var e=t.getBoundingClientRect();return e.top>=0&&e.left>=0&&e.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&e.right<=(window.innerWidth||document.documentElement.clientWidth)}function a(t){var e=window.getComputedStyle(t),i=parseFloat(e.paddingLeft)+parseFloat(e.paddingRight);return t.clientWidth-i}function s(t,e,i){var a=void 0,s=void 0;return t<=e?(s=t,0===(a=e-t)&&(s-=a=.01*i)):(s=e,0===(a=t-e)&&(a=.01*i)),[a,s]}function n(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function r(t,e){var i=document.createElementNS("http://www.w3.org/2000/svg",t);for(var a in e){var s=e[a];if("inside"===a)n(s).appendChild(i);else if("around"===a){var r=n(s);r.parentNode.insertBefore(i,r),i.appendChild(r)}else"styles"===a?"object"===(void 0===s?"undefined":W(s))&&Object.keys(s).map(function(t){i.style[t]=s[t]}):("className"===a&&(a="class"),"innerHTML"===a?i.textContent=s:i.setAttribute(a,s))}return i}function o(t,e){return r("linearGradient",{inside:t,id:e,x1:0,x2:0,y1:0,y2:1})}function l(t,e,i,a){return r("stop",{inside:t,style:"stop-color: "+i,offset:e,"stop-opacity":a})}function h(t,e,i,a){return r("svg",{className:e,inside:t,width:i,height:a})}function u(t){return r("defs",{inside:t})}function c(t,e){return r("g",{className:e,inside:t,transform:arguments.length>2&&void 0!==arguments[2]?arguments[2]:""})}function _(t){return r("path",{className:arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",d:t,styles:{stroke:arguments.length>2&&void 0!==arguments[2]?arguments[2]:"none",fill:arguments.length>3&&void 0!==arguments[3]?arguments[3]:"none"}})}function p(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a="path-fill-gradient-"+e,s=o(t,a),n=[1,.6,.2];return i&&(n=[.4,.2,0]),l(s,"0%",e,n[0]),l(s,"50%",e,n[1]),l(s,"100%",e,n[2]),a}function d(t,e,i,a){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"none",n=arguments.length>5&&void 0!==arguments[5]?arguments[5]:{},o={className:t,x:e,y:i,width:a,height:a,fill:s};return Object.keys(n).map(function(t){o[t]=n[t]}),r("rect",o)}function v(t,e,i,a){return r("text",{className:t,x:e,y:i,dy:".32em",innerHTML:a})}function f(t,e,i,a,s,n){var o=r("line",{x1:0,x2:0,y1:0,y2:t}),l=r("text",{className:a,x:0,y:e,dy:".71em",innerHTML:i}),h=r("g",{className:"tick "+s,transform:"translate("+n+", 0)"});return h.appendChild(o),h.appendChild(l),h}function m(t,e,i,a,s,n,o){var l=arguments.length>7&&void 0!==arguments[7]&&arguments[7],h=r("line",{className:"dashed"===(arguments.length>8&&void 0!==arguments[8]?arguments[8]:"")?"dashed":"",x1:t,x2:e,y1:0,y2:0}),u=r("text",{className:s,x:i,y:0,dy:".32em",innerHTML:a+""}),c=r("g",{className:"tick "+n,transform:"translate(0, "+o+")","stroke-opacity":1});return l&&(h.style.stroke="rgba(27, 31, 35, 0.6)"),c.appendChild(h),c.appendChild(u),c}function g(t,e,i){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"linear",s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:void 0,n=arguments.length>5&&void 0!==arguments[5]?arguments[5]:{},r=t.cloneNode(!0),o=t.cloneNode(!0);for(var l in e){var h=void 0;h="transform"===l?document.createElementNS("http://www.w3.org/2000/svg","animateTransform"):document.createElementNS("http://www.w3.org/2000/svg","animate");var u=n[l]||t.getAttribute(l),c=e[l],_={attributeName:l,from:u,to:c,begin:"0s",dur:i/1e3+"s",values:u+";"+c,keySplines:V[a],keyTimes:"0;1",calcMode:"spline",fill:"freeze"};s&&(_.type=s);for(var p in _)h.setAttribute(p,_[p]);r.appendChild(h),s?o.setAttribute(l,"translate("+c+")"):o.setAttribute(l,c)}return[r,o]}function y(t,e){t.style.transform=e,t.style.webkitTransform=e,t.style.msTransform=e,t.style.mozTransform=e,t.style.oTransform=e}function x(t,e){var i=[],a=[];e.map(function(t){var e=t[0],s=e.unit
|
|
|
|
;
|
|
|
|
'use strict';
|
|
|
|
|
2017-12-10 21:26:54 +10:30
|
|
|
System.register('flarum/statistics/components/StatisticsWidget', ['flarum/components/DashboardWidget', 'flarum/components/SelectDropdown', 'flarum/components/Button', 'flarum/helpers/icon', 'flarum/helpers/listItems', 'flarum/utils/ItemList', 'flarum/utils/abbreviateNumber'], function (_export, _context) {
|
2017-12-10 21:11:13 +10:30
|
|
|
"use strict";
|
|
|
|
|
2017-12-10 21:26:54 +10:30
|
|
|
var DashboardWidget, SelectDropdown, Button, icon, listItems, ItemList, abbreviateNumber, StatisticsWidget;
|
2017-12-10 21:11:13 +10:30
|
|
|
return {
|
|
|
|
setters: [function (_flarumComponentsDashboardWidget) {
|
|
|
|
DashboardWidget = _flarumComponentsDashboardWidget.default;
|
|
|
|
}, function (_flarumComponentsSelectDropdown) {
|
|
|
|
SelectDropdown = _flarumComponentsSelectDropdown.default;
|
|
|
|
}, function (_flarumComponentsButton) {
|
|
|
|
Button = _flarumComponentsButton.default;
|
|
|
|
}, function (_flarumHelpersIcon) {
|
|
|
|
icon = _flarumHelpersIcon.default;
|
|
|
|
}, function (_flarumHelpersListItems) {
|
|
|
|
listItems = _flarumHelpersListItems.default;
|
|
|
|
}, function (_flarumUtilsItemList) {
|
|
|
|
ItemList = _flarumUtilsItemList.default;
|
2017-12-10 21:26:54 +10:30
|
|
|
}, function (_flarumUtilsAbbreviateNumber) {
|
|
|
|
abbreviateNumber = _flarumUtilsAbbreviateNumber.default;
|
2017-12-10 21:11:13 +10:30
|
|
|
}],
|
|
|
|
execute: function () {
|
|
|
|
StatisticsWidget = function (_DashboardWidget) {
|
|
|
|
babelHelpers.inherits(StatisticsWidget, _DashboardWidget);
|
|
|
|
|
|
|
|
function StatisticsWidget() {
|
|
|
|
babelHelpers.classCallCheck(this, StatisticsWidget);
|
|
|
|
return babelHelpers.possibleConstructorReturn(this, (StatisticsWidget.__proto__ || Object.getPrototypeOf(StatisticsWidget)).apply(this, arguments));
|
|
|
|
}
|
|
|
|
|
|
|
|
babelHelpers.createClass(StatisticsWidget, [{
|
|
|
|
key: 'init',
|
|
|
|
value: function init() {
|
|
|
|
babelHelpers.get(StatisticsWidget.prototype.__proto__ || Object.getPrototypeOf(StatisticsWidget.prototype), 'init', this).call(this);
|
|
|
|
|
2017-12-11 22:42:51 +10:30
|
|
|
// Create a Date object which represents the start of the day in the
|
|
|
|
// configured timezone. To do this we convert a UTC time into that timezone,
|
|
|
|
// reset to the first hour of the day, and then convert back into UTC time.
|
|
|
|
// We'll be working with seconds rather than milliseconds throughout too.
|
|
|
|
var today = new Date();
|
2017-12-19 08:57:55 +10:30
|
|
|
today.setTime(today.getTime() + app.data.statistics.timezoneOffset * 1000);
|
2017-12-11 22:42:51 +10:30
|
|
|
today.setUTCHours(0, 0, 0, 0);
|
2017-12-19 08:57:55 +10:30
|
|
|
today.setTime(today.getTime() - app.data.statistics.timezoneOffset * 1000);
|
2017-12-11 22:42:51 +10:30
|
|
|
today = today / 1000;
|
2017-12-10 21:11:13 +10:30
|
|
|
|
|
|
|
this.entities = ['users', 'discussions', 'posts'];
|
|
|
|
this.periods = {
|
2017-12-11 19:01:38 +10:30
|
|
|
today: { start: today, end: today + 86400, step: 3600 },
|
|
|
|
last_7_days: { start: today - 86400 * 7, end: today, step: 86400 },
|
|
|
|
last_28_days: { start: today - 86400 * 28, end: today, step: 86400 },
|
|
|
|
last_12_months: { start: today - 86400 * 364, end: today, step: 86400 * 7 }
|
2017-12-10 21:11:13 +10:30
|
|
|
};
|
|
|
|
|
|
|
|
this.selectedEntity = 'users';
|
2017-12-10 21:26:54 +10:30
|
|
|
this.selectedPeriod = 'last_7_days';
|
2017-12-10 21:11:13 +10:30
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'className',
|
|
|
|
value: function className() {
|
|
|
|
return 'StatisticsWidget';
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'content',
|
|
|
|
value: function content() {
|
|
|
|
var _this2 = this;
|
|
|
|
|
|
|
|
var thisPeriod = this.periods[this.selectedPeriod];
|
|
|
|
|
|
|
|
return m(
|
|
|
|
'div',
|
|
|
|
{ className: 'StatisticsWidget-table' },
|
|
|
|
m(
|
|
|
|
'div',
|
|
|
|
{ className: 'StatisticsWidget-labels' },
|
|
|
|
m(
|
|
|
|
'div',
|
|
|
|
{ className: 'StatisticsWidget-label' },
|
|
|
|
app.translator.trans('flarum-statistics.admin.statistics.total_label')
|
|
|
|
),
|
|
|
|
m(
|
|
|
|
'div',
|
|
|
|
{ className: 'StatisticsWidget-label' },
|
|
|
|
m(
|
|
|
|
SelectDropdown,
|
|
|
|
{ buttonClassName: 'Button Button--text', caretIcon: 'caret-down' },
|
|
|
|
Object.keys(this.periods).map(function (period) {
|
|
|
|
return m(
|
|
|
|
Button,
|
2017-12-11 19:01:38 +10:30
|
|
|
{
|
|
|
|
active: period === _this2.selectedPeriod,
|
|
|
|
onclick: _this2.changePeriod.bind(_this2, period),
|
|
|
|
icon: period === _this2.selectedPeriod ? 'check' : true },
|
2017-12-10 21:11:13 +10:30
|
|
|
app.translator.trans('flarum-statistics.admin.statistics.' + period + '_label')
|
|
|
|
);
|
|
|
|
})
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
this.entities.map(function (entity) {
|
2017-12-10 21:26:54 +10:30
|
|
|
var totalCount = _this2.getTotalCount(entity);
|
2017-12-10 21:11:13 +10:30
|
|
|
var thisPeriodCount = _this2.getPeriodCount(entity, thisPeriod);
|
|
|
|
var lastPeriodCount = _this2.getPeriodCount(entity, _this2.getLastPeriod(thisPeriod));
|
|
|
|
var periodChange = lastPeriodCount > 0 && (thisPeriodCount - lastPeriodCount) / lastPeriodCount * 100;
|
|
|
|
|
|
|
|
return m(
|
|
|
|
'a',
|
|
|
|
{ className: 'StatisticsWidget-entity' + (_this2.selectedEntity === entity ? ' active' : ''), onclick: _this2.changeEntity.bind(_this2, entity) },
|
|
|
|
m(
|
|
|
|
'h3',
|
|
|
|
{ className: 'StatisticsWidget-heading' },
|
|
|
|
app.translator.trans('flarum-statistics.admin.statistics.' + entity + '_heading')
|
|
|
|
),
|
|
|
|
m(
|
|
|
|
'div',
|
2017-12-10 21:26:54 +10:30
|
|
|
{ className: 'StatisticsWidget-total', title: totalCount },
|
|
|
|
abbreviateNumber(totalCount)
|
2017-12-10 21:11:13 +10:30
|
|
|
),
|
|
|
|
m(
|
|
|
|
'div',
|
2017-12-10 21:26:54 +10:30
|
|
|
{ className: 'StatisticsWidget-period', title: thisPeriodCount },
|
|
|
|
abbreviateNumber(thisPeriodCount),
|
2017-12-10 21:11:13 +10:30
|
|
|
' ',
|
|
|
|
periodChange ? m(
|
|
|
|
'span',
|
|
|
|
{ className: 'StatisticsWidget-change StatisticsWidget-change--' + (periodChange > 0 ? 'up' : 'down') },
|
|
|
|
icon('arrow-' + (periodChange > 0 ? 'up' : 'down')),
|
|
|
|
Math.abs(periodChange.toFixed(1)),
|
|
|
|
'%'
|
|
|
|
) : ''
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
m('div', { className: 'StatisticsWidget-chart', config: this.drawChart.bind(this) })
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'drawChart',
|
|
|
|
value: function drawChart(elm, isInitialized, context) {
|
2017-12-11 19:01:38 +10:30
|
|
|
if (context.chart && context.entity === this.selectedEntity && context.period === this.selectedPeriod) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-19 08:57:55 +10:30
|
|
|
var offset = app.data.statistics.timezoneOffset;
|
2017-12-10 21:11:13 +10:30
|
|
|
var period = this.periods[this.selectedPeriod];
|
2017-12-11 19:01:38 +10:30
|
|
|
var periodLength = period.end - period.start;
|
2017-12-10 21:11:13 +10:30
|
|
|
var labels = [];
|
|
|
|
var thisPeriod = [];
|
|
|
|
var lastPeriod = [];
|
|
|
|
|
2017-12-11 19:01:38 +10:30
|
|
|
for (var i = period.start; i < period.end; i += period.step) {
|
|
|
|
var label = void 0;
|
|
|
|
|
|
|
|
if (period.step < 86400) {
|
2017-12-11 22:42:51 +10:30
|
|
|
label = moment.unix(i + offset).utc().format('h A');
|
2017-12-11 19:01:38 +10:30
|
|
|
} else {
|
2017-12-11 22:42:51 +10:30
|
|
|
label = moment.unix(i + offset).utc().format('D MMM');
|
2017-12-11 07:52:48 +10:30
|
|
|
|
2017-12-11 19:01:38 +10:30
|
|
|
if (period.step > 86400) {
|
2017-12-11 22:42:51 +10:30
|
|
|
label += ' - ' + moment.unix(i + offset + period.step - 1).utc().format('D MMM');
|
2017-12-11 19:01:38 +10:30
|
|
|
}
|
|
|
|
}
|
2017-12-11 07:52:48 +10:30
|
|
|
|
2017-12-11 19:01:38 +10:30
|
|
|
labels.push(label);
|
|
|
|
|
|
|
|
thisPeriod.push(this.getPeriodCount(this.selectedEntity, { start: i, end: i + period.step }));
|
|
|
|
|
|
|
|
lastPeriod.push(this.getPeriodCount(this.selectedEntity, { start: i - periodLength, end: i - periodLength + period.step }));
|
2017-12-10 21:11:13 +10:30
|
|
|
}
|
|
|
|
|
2017-12-11 19:01:38 +10:30
|
|
|
var datasets = [{ values: lastPeriod }, { values: thisPeriod }];
|
2017-12-10 21:11:13 +10:30
|
|
|
|
|
|
|
if (!context.chart) {
|
|
|
|
context.chart = new Chart({
|
|
|
|
parent: elm,
|
|
|
|
data: { labels: labels, datasets: datasets },
|
|
|
|
type: 'line',
|
|
|
|
height: 200,
|
2017-12-11 07:52:48 +10:30
|
|
|
x_axis_mode: 'tick',
|
|
|
|
y_axis_mode: 'span',
|
2017-12-10 21:11:13 +10:30
|
|
|
is_series: 1,
|
|
|
|
show_dots: 0,
|
2017-12-11 22:42:51 +10:30
|
|
|
colors: ['rgba(127, 127, 127, 0.2)', app.forum.attribute('themePrimaryColor')]
|
2017-12-10 21:11:13 +10:30
|
|
|
});
|
2017-12-11 19:01:38 +10:30
|
|
|
} else {
|
|
|
|
context.chart.update_values(datasets, labels);
|
2017-12-10 21:11:13 +10:30
|
|
|
}
|
|
|
|
|
2017-12-11 19:01:38 +10:30
|
|
|
context.entity = this.selectedEntity;
|
|
|
|
context.period = this.selectedPeriod;
|
2017-12-10 21:11:13 +10:30
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'changeEntity',
|
|
|
|
value: function changeEntity(entity) {
|
|
|
|
this.selectedEntity = entity;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'changePeriod',
|
|
|
|
value: function changePeriod(period) {
|
|
|
|
this.selectedPeriod = period;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'getTotalCount',
|
|
|
|
value: function getTotalCount(entity) {
|
|
|
|
return app.data.statistics[entity].total;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'getPeriodCount',
|
|
|
|
value: function getPeriodCount(entity, period) {
|
2017-12-11 22:42:51 +10:30
|
|
|
var timed = app.data.statistics[entity].timed;
|
2017-12-10 21:11:13 +10:30
|
|
|
var count = 0;
|
|
|
|
|
2017-12-11 22:42:51 +10:30
|
|
|
for (var time in timed) {
|
|
|
|
if (time >= period.start && time < period.end) {
|
|
|
|
count += timed[time];
|
2017-12-10 21:11:13 +10:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'getLastPeriod',
|
|
|
|
value: function getLastPeriod(thisPeriod) {
|
|
|
|
return {
|
|
|
|
start: thisPeriod.start - (thisPeriod.end - thisPeriod.start),
|
|
|
|
end: thisPeriod.start
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}]);
|
|
|
|
return StatisticsWidget;
|
|
|
|
}(DashboardWidget);
|
|
|
|
|
|
|
|
_export('default', StatisticsWidget);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});;
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
System.register('flarum/statistics/main', ['flarum/app', 'flarum/extend', 'flarum/components/DashboardPage', 'flarum/statistics/components/StatisticsWidget'], function (_export, _context) {
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
var app, extend, DashboardPage, StatisticsWidget;
|
|
|
|
return {
|
|
|
|
setters: [function (_flarumApp) {
|
|
|
|
app = _flarumApp.default;
|
|
|
|
}, function (_flarumExtend) {
|
|
|
|
extend = _flarumExtend.extend;
|
|
|
|
}, function (_flarumComponentsDashboardPage) {
|
|
|
|
DashboardPage = _flarumComponentsDashboardPage.default;
|
|
|
|
}, function (_flarumStatisticsComponentsStatisticsWidget) {
|
|
|
|
StatisticsWidget = _flarumStatisticsComponentsStatisticsWidget.default;
|
|
|
|
}],
|
|
|
|
execute: function () {
|
|
|
|
|
|
|
|
app.initializers.add('flarum-statistics', function () {
|
|
|
|
extend(DashboardPage.prototype, 'availableWidgets', function (widgets) {
|
|
|
|
widgets.push(m(StatisticsWidget, null));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|