Issue #1189 : Add a compare mode on years and month in the statistic page.

* Number of years compared is a configuration variable (default 5)
 * Months compared are the actual, the last and the actual month the last year (you can also visualize the average last 12 months)
This commit is contained in:
Zacharie
2020-06-08 15:03:03 +02:00
committed by plegall
parent 8577239be5
commit 5d24541dca
5 changed files with 303 additions and 45 deletions
+158 -37
View File
@@ -6,6 +6,8 @@ data["hours"] = $("#data").data("hours")[0];
data["days"] = $("#data").data("days")[0];
data["months"] = $("#data").data("months")[0];
data["years"] = $("#data").data("years")[0];
data["compare-years"] = $("#data").data("compare-years")[0];
data["month-stats"] = $("#data").data("month-stats")[0];
data_unit = {
"hours":"day",
@@ -14,17 +16,21 @@ data_unit = {
"years": "year"
}
compareMode = false;
/*-------
Creating graph
-------*/
var ctx = document.getElementById('stat-graph').getContext('2d');
//Create the gradient under the curve
var gradient = ctx.createLinearGradient(0,400, 0,0);
gradient.addColorStop(0, 'rgba(255,119,0,0)');
gradient.addColorStop(1, 'rgba(255,119,0,1)');
function gradient(r, g, b) {
let gradient = ctx.createLinearGradient(0,400, 0,0);
gradient.addColorStop(0, 'rgba('+r+','+g+','+b+',0)');
gradient.addColorStop(1, 'rgba('+r+','+g+','+b+',1)');
return gradient;
}
//Setup the graph
Chart.defaults.global.legend.display = false;
Chart.defaults.global.elements.point.radius = 0.1;
Chart.defaults.global.elements.point.hitRadius = 10
Chart.defaults.global.defaultFontSize = 14;
@@ -32,45 +38,79 @@ Chart.defaults.global.defaultFontColor = '#888';
Chart.defaults.global.tooltips.mode = 'index';
Chart.defaults.global.tooltips.intersect = false;
Chart.defaults.global.legend.onClick = null;
var statGraph = new Chart(ctx, {
type: 'line',
maintainAspectRatio: false,
options: {
scales: {
xAxes: [{
type: 'time',
time: {
tooltipFormat: 'll'
},
gridLines: {
display: false
}
}],
}
}
});
//Line options
var displayOptions = {
backgroundColor: gradient,
backgroundColor: gradient(255, 119, 0),
borderColor: 'rgba(255,119,0,1)',
lineTension : 0.2
}
function changeData(dataType, label, options = displayOptions) {
statGraph.data = {
datasets: [{
label: label,
data: getValues(data[dataType]),
...options
}]
function changeData(dataType, options = displayOptions) {
if (!compareMode) {
statGraph.data = {
datasets: [{
label: str_number_page_visited,
data: getValues(data[dataType]),
...options
}]
}
statGraph.options = {
scales: {
xAxes: [{
type: 'time',
time: {
tooltipFormat: 'll'
},
gridLines: {
display: false
}
}],
},
legend: {
display:false
}
}
statGraph.options.scales.xAxes.forEach(axe => {
axe.time.tooltipFormat = str_tooltip_format[dataType];
axe.time.unit = data_unit[dataType];
axe.time.displayFormats = str_unit_format;
})
statGraph.update();
} else {
statGraph.options.legend.display = true;
if (dataType == "years") {
statGraph.data = {
datasets: getComparedYearDataset()
}
statGraph.options.scales = {
xAxes: [{
type: 'category',
labels: str_months
}]
}
} else if (dataType == "months") {
days = [];
for (let i = 1; i<=31; i++) {
days.push(i);
}
statGraph.data = {
datasets: getMonthStatsDataset()
}
statGraph.options.scales = {
xAxes: [{
type: 'category',
labels : days
}]
}
}
statGraph.update();
}
statGraph.options.scales.xAxes.forEach(axe => {
axe.time.tooltipFormat = str_tooltip_format[dataType];
axe.time.unit = data_unit[dataType];
axe.time.displayFormats = str_unit_format;
})
statGraph.update();
}
//Make Data readable by Chart.js
@@ -78,24 +118,105 @@ function getValues(data) {
values = [];
Object.keys(data).forEach(function(key) {
var newPoint = {
x:new Date(key),
y:data[key]
x:new Date(key),
y:data[key]
}
values.push(newPoint)
});
return values;
}
function getComparedYearDataset() {
colors = ["#ffa744", "#ff5252", "#896af3", "#2883c3", "#6ece5e"]
values = {};
dataset = [];
Object.keys(data["compare-years"]).forEach(function(key) {
date = new Date(key)
if (values[date.getFullYear()] == undefined) {
values[date.getFullYear()] = [];
}
values[date.getFullYear()][parseInt(date.getMonth())] = data["compare-years"][key];
});
Object.keys(values).forEach(function(key) {
dataset.push({
label : str_number_page_visited_with_year.replace('%s', key),
data : values[key],
lineTension : 0.2,
borderColor : colors[parseInt(key) % colors.length],
backgroundColor: "rgba(0,0,0,0)"
})
});
return dataset;
}
function getMonthStatsDataset() {
colors = ["#ffa744", "#ff5252", "#896af3", "#2883c3", "#6ece5e"]
dataset = [];
colorIndice = 0;
let date;
data["month-stats"]["month"].forEach(values => {
let days_data = [];
Object.keys(values).forEach(function(key) {
date = new Date(key)
days_data[parseInt(date.getUTCDate()) - 1] = values[key];
});
console.log(days_data);
dataset.push({
label : str_number_page_visited_with_year.replace('%s', str_months[date.getMonth()]+" "+date.getFullYear()),
data : days_data,
lineTension : 0.2,
borderColor : colors[colorIndice % colors.length],
backgroundColor: "rgba(0,0,0,0)"
})
colorIndice++
});
averageTab = [];
for (let i = 0; i < 31; i++) {
averageTab[i] = data["month-stats"]["avg"];
}
dataset.push({
label : str_avg,
data : averageTab,
lineTension : 0.2,
borderColor : colors[4],
backgroundColor: "rgba(0,0,0,0)"
})
return dataset;
}
//Event listener
$(".stat-data-selector label").on("click", function(){
let dataType = $(this).data("value");
changeData(dataType, str_number_page_visited)
dataType = $(this).data("value");
changeData(dataType);
})
$(".stat-compare-mode input").on("change", function(){
compareMode = $(this)[0].checked;
if (compareMode) {
$("#hours-selector + label, #days-selector + label").addClass('unavailable');
if ($("#hours-selector").prop('checked')||$("#days-selector").prop('checked')) {
$("#years-selector").prop('checked', true);
$("#hours-selector, #days-selector").prop('checked', false);
changeData("years");
} else {
changeData($(".stat-data-selector input:checked + label").data("value"))
}
} else {
$("#hours-selector + label, #days-selector + label").removeClass('unavailable');
changeData($(".stat-data-selector input:checked + label").data("value"));
}
})
/*-------
Initialize the page
-------*/
$(function() {
let dataType = $(".stat-data-selector input:checked + label").data("value");
changeData(dataType, str_number_page_visited)
changeData($(".stat-data-selector input:checked + label").data("value"));
})
+19 -1
View File
@@ -1,5 +1,6 @@
{footer_script}
var str_number_page_visited = "{'Page Visited'|@translate}";
var str_number_page_visited_with_year = "{'Page Visited in %s'|@translate}";
var str_tooltip_format = {
"years":"YYYY",
"months":"MMMM YYYY",
@@ -10,6 +11,8 @@ var str_unit_format = {
"day":"dddd",
"month":"MMM YYYY"
}
var str_avg = "{'Average last 12 months'|@translate}"
var str_months = ["{'January'|@translate}", "{'February'|@translate}", "{'March'|@translate}", "{'April'|@translate}", "{'May'|@translate}", "{'June'|@translate}", "{'July'|@translate}", "{'August'|@translate}", "{'September'|@translate}", "{'Octobember'|@translate}", "{'November'|@translate}", "{'December'|@translate}"];
moment.locale("{$langCode}");
{/footer_script}
@@ -24,7 +27,22 @@ moment.locale("{$langCode}");
<h2>{'History'|@translate}</h2>
</div>
<div id="data" data-hours='{json_encode($lastHours)}' data-days='{json_encode($lastDays)}' data-months='{json_encode($lastMonths)}' data-years='{json_encode($lastYears)}'></div>
<div class="stat-compare-mode">
<label class="switch">
<input type="checkbox" id="toggleCompareMode">
<span class="slider round" checked="false"></span>
</label>
{'Compare mode'|@translate}
</div>
<div id="data"
data-hours='{json_encode($lastHours)}'
data-days='{json_encode($lastDays)}'
data-months='{json_encode($lastMonths)}'
data-years='{json_encode($lastYears)}'
data-compare-years='{json_encode($compareYears)}'
data-month-stats='{json_encode($monthStats)}'
></div>
<div class="stat-legend-container">
<div class="stat-data-selector">
<input type="radio" id="hours-selector" name="stat-data-type">
+14
View File
@@ -266,6 +266,13 @@ TABLE.doubleSelect SELECT.categoryList {
transition: 0.2s ease;
}
.stat-data-selector label.unavailable {
color: gray;
background-color: #aaa;
cursor: default;
pointer-events: none;
}
.stat-data-selector label:hover {
background-color: #ccc
}
@@ -273,6 +280,7 @@ TABLE.doubleSelect SELECT.categoryList {
.stat-data-selector input:checked + label {
background-color: #FFA646;
color: white;
pointer-events: none;
}
.stat-data-selector input{
@@ -287,6 +295,12 @@ TABLE.doubleSelect SELECT.categoryList {
margin-bottom: 20px;
}
.stat-compare-mode {
position: absolute;
right: 10px;
transform: translate(0, 10px);
}
.over{
position: relative;
z-index: 0;