discourse/app/assets/javascripts/admin/components/dashboard-mini-chart.js.es6

165 lines
4.0 KiB
JavaScript

import { ajax } from "discourse/lib/ajax";
import AsyncReport from "admin/mixins/async-report";
import Report from "admin/models/report";
import { number } from 'discourse/lib/formatter';
import loadScript from "discourse/lib/load-script";
import { registerTooltip, unregisterTooltip } from "discourse/lib/tooltip";
function collapseWeekly(data, average) {
let aggregate = [];
let bucket, i;
let offset = data.length % 7;
for(i = offset; i < data.length; i++) {
if (bucket && (i % 7 === offset)) {
if (average) {
bucket.y = parseFloat((bucket.y / 7.0).toFixed(2));
}
aggregate.push(bucket);
bucket = null;
}
bucket = bucket || { x: data[i].x, y: 0 };
bucket.y += data[i].y;
}
return aggregate;
}
export default Ember.Component.extend(AsyncReport, {
classNames: ["chart", "dashboard-mini-chart"],
total: 0,
init() {
this._super();
this._colorsPool = ["rgb(0,136,204)", "rgb(235,83,148)"];
},
didRender() {
this._super();
registerTooltip($(this.element).find("[data-tooltip]"));
},
willDestroyElement() {
this._super();
unregisterTooltip($(this.element).find("[data-tooltip]"));
},
pickColorAtIndex(index) {
return this._colorsPool[index] || this._colorsPool[0];
},
fetchReport() {
this._super();
let payload = this.buildPayload(["prev_period"]);
if (this._chart) {
this._chart.destroy();
this._chart = null;
}
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => {
return ajax(dataSource, payload)
.then(response => {
this.get("reports").pushObject(this.loadReport(response.report));
});
}));
},
loadReport(report, previousReport) {
Report.fillMissingDates(report);
if (report.data && report.data.length > 40) {
report.data = collapseWeekly(report.data, report.average);
}
if (previousReport && previousReport.color.length) {
report.color = previousReport.color;
} else {
const dataSourceNameIndex = this.get("dataSourceNames").split(",").indexOf(report.type);
report.color = this.pickColorAtIndex(dataSourceNameIndex);
}
return Report.create(report);
},
renderReport() {
this._super();
Ember.run.schedule("afterRender", () => {
const $chartCanvas = this.$(".chart-canvas");
if (!$chartCanvas.length) return;
const context = $chartCanvas[0].getContext("2d");
const reportsForPeriod = this.get("reportsForPeriod");
const labels = Ember.makeArray(reportsForPeriod.get("firstObject.data")).map(d => d.x);
const data = {
labels,
datasets: reportsForPeriod.map(report => {
return {
data: Ember.makeArray(report.data).map(d => d.y),
backgroundColor: "rgba(200,220,240,0.3)",
borderColor: report.color
};
})
};
if (this._chart) {
this._chart.destroy();
this._chart = null;
}
loadScript("/javascripts/Chart.min.js").then(() => {
if (this._chart) {
this._chart.destroy();
}
this._chart = new window.Chart(context, this._buildChartConfig(data));
});
});
},
_buildChartConfig(data) {
return {
type: "line",
data,
options: {
tooltips: {
callbacks: {
title: (context) => moment(context[0].xLabel, "YYYY-MM-DD").format("LL")
}
},
legend: {
display: false
},
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
left: 0,
top: 0,
right: 0,
bottom: 0
}
},
scales: {
yAxes: [{
display: true,
ticks: { callback: (label) => number(label) }
}],
xAxes: [{
display: true,
gridLines: { display: false },
type: "time",
time: {
parser: "YYYY-MM-DD"
}
}],
}
},
};
}
});