2021-06-17 15:15:20 +08:00
|
|
|
import Report from "admin/models/report";
|
2019-10-24 00:30:52 +08:00
|
|
|
import Component from "@ember/component";
|
2020-12-18 21:18:52 +08:00
|
|
|
import discourseDebounce from "discourse-common/lib/debounce";
|
2019-01-21 22:17:04 +08:00
|
|
|
import loadScript from "discourse/lib/load-script";
|
2019-11-02 01:06:50 +08:00
|
|
|
import { makeArray } from "discourse-common/lib/helpers";
|
2019-01-21 22:17:04 +08:00
|
|
|
import { number } from "discourse/lib/formatter";
|
2020-12-18 21:18:52 +08:00
|
|
|
import { schedule } from "@ember/runloop";
|
2021-11-16 17:26:26 +08:00
|
|
|
import { bind } from "discourse-common/utils/decorators";
|
2019-01-21 22:17:04 +08:00
|
|
|
|
2019-10-24 00:30:52 +08:00
|
|
|
export default Component.extend({
|
2019-01-21 22:17:04 +08:00
|
|
|
classNames: ["admin-report-chart", "admin-report-stacked-chart"],
|
|
|
|
|
|
|
|
didInsertElement() {
|
|
|
|
this._super(...arguments);
|
|
|
|
|
2021-11-16 17:26:26 +08:00
|
|
|
window.addEventListener("resize", this._resizeHandler);
|
2019-01-21 22:17:04 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
willDestroyElement() {
|
|
|
|
this._super(...arguments);
|
|
|
|
|
2021-11-16 17:26:26 +08:00
|
|
|
window.removeEventListener("resize", this._resizeHandler);
|
2019-01-21 22:17:04 +08:00
|
|
|
this._resetChart();
|
|
|
|
},
|
|
|
|
|
|
|
|
didReceiveAttrs() {
|
|
|
|
this._super(...arguments);
|
|
|
|
|
2020-12-18 21:18:52 +08:00
|
|
|
discourseDebounce(this, this._scheduleChartRendering, 100);
|
2019-01-21 22:17:04 +08:00
|
|
|
},
|
|
|
|
|
2021-11-16 17:26:26 +08:00
|
|
|
@bind
|
|
|
|
_resizeHandler() {
|
|
|
|
discourseDebounce(this, this._scheduleChartRendering, 500);
|
|
|
|
},
|
|
|
|
|
2019-01-21 22:17:04 +08:00
|
|
|
_scheduleChartRendering() {
|
2019-10-30 21:48:24 +08:00
|
|
|
schedule("afterRender", () => {
|
2019-10-03 05:54:30 +08:00
|
|
|
if (!this.element) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-07-16 18:45:15 +08:00
|
|
|
this._renderChart(
|
|
|
|
this.model,
|
|
|
|
this.element.querySelector(".chart-canvas")
|
|
|
|
);
|
2019-01-21 22:17:04 +08:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2019-07-16 18:45:15 +08:00
|
|
|
_renderChart(model, chartCanvas) {
|
2020-09-22 22:28:28 +08:00
|
|
|
if (!chartCanvas) {
|
|
|
|
return;
|
|
|
|
}
|
2019-01-21 22:17:04 +08:00
|
|
|
|
2019-07-16 18:45:15 +08:00
|
|
|
const context = chartCanvas.getContext("2d");
|
2019-01-21 22:17:04 +08:00
|
|
|
|
2022-04-27 20:04:09 +08:00
|
|
|
const chartData = makeArray(model.chartData || model.data).map((cd) => {
|
|
|
|
return {
|
|
|
|
label: cd.label,
|
|
|
|
color: cd.color,
|
|
|
|
data: Report.collapse(model, cd.data),
|
|
|
|
};
|
|
|
|
});
|
2019-01-21 22:17:04 +08:00
|
|
|
|
|
|
|
const data = {
|
2019-12-11 22:49:17 +08:00
|
|
|
labels: chartData[0].data.mapBy("x"),
|
2019-01-21 22:17:04 +08:00
|
|
|
datasets: chartData.map((cd) => {
|
|
|
|
return {
|
2019-01-22 00:10:10 +08:00
|
|
|
label: cd.label,
|
2019-01-21 22:17:04 +08:00
|
|
|
stack: "pageviews-stack",
|
2022-04-27 20:04:09 +08:00
|
|
|
data: cd.data,
|
2019-01-21 22:17:04 +08:00
|
|
|
backgroundColor: cd.color,
|
|
|
|
};
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
|
|
|
loadScript("/javascripts/Chart.min.js").then(() => {
|
|
|
|
this._resetChart();
|
2019-12-11 22:49:17 +08:00
|
|
|
|
2019-01-21 22:17:04 +08:00
|
|
|
this._chart = new window.Chart(context, this._buildChartConfig(data));
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
_buildChartConfig(data) {
|
|
|
|
return {
|
|
|
|
type: "bar",
|
|
|
|
data,
|
|
|
|
options: {
|
2019-01-22 18:20:50 +08:00
|
|
|
responsive: true,
|
|
|
|
maintainAspectRatio: false,
|
2019-12-11 22:49:17 +08:00
|
|
|
responsiveAnimationDuration: 0,
|
2019-01-21 22:17:04 +08:00
|
|
|
hover: { mode: "index" },
|
2019-12-11 22:49:17 +08:00
|
|
|
animation: {
|
|
|
|
duration: 0,
|
|
|
|
},
|
2021-08-23 19:49:49 +08:00
|
|
|
plugins: {
|
|
|
|
tooltip: {
|
|
|
|
mode: "index",
|
|
|
|
intersect: false,
|
|
|
|
callbacks: {
|
|
|
|
beforeFooter: (tooltipItem) => {
|
|
|
|
let total = 0;
|
|
|
|
tooltipItem.forEach(
|
|
|
|
(item) => (total += parseInt(item.parsed.y || 0, 10))
|
|
|
|
);
|
|
|
|
return `= ${total}`;
|
|
|
|
},
|
|
|
|
title: (tooltipItem) =>
|
|
|
|
moment(tooltipItem[0].label, "YYYY-MM-DD").format("LL"),
|
2019-01-22 16:57:34 +08:00
|
|
|
},
|
2019-01-21 22:17:04 +08:00
|
|
|
},
|
|
|
|
},
|
2021-08-23 19:49:49 +08:00
|
|
|
|
2019-01-21 22:17:04 +08:00
|
|
|
layout: {
|
|
|
|
padding: {
|
|
|
|
left: 0,
|
|
|
|
top: 0,
|
|
|
|
right: 0,
|
|
|
|
bottom: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
scales: {
|
2021-08-23 19:49:49 +08:00
|
|
|
y: [
|
2019-01-21 22:17:04 +08:00
|
|
|
{
|
|
|
|
stacked: true,
|
|
|
|
display: true,
|
|
|
|
ticks: {
|
2019-12-11 22:49:17 +08:00
|
|
|
callback: (label) => number(label),
|
|
|
|
sampleSize: 5,
|
|
|
|
maxRotation: 25,
|
|
|
|
minRotation: 25,
|
2019-01-21 22:17:04 +08:00
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
2021-08-23 19:49:49 +08:00
|
|
|
x: [
|
2019-01-21 22:17:04 +08:00
|
|
|
{
|
|
|
|
display: true,
|
|
|
|
gridLines: { display: false },
|
|
|
|
type: "time",
|
|
|
|
time: {
|
2021-06-17 15:15:20 +08:00
|
|
|
unit: Report.unitForDatapoints(data.labels.length),
|
2019-12-11 22:49:17 +08:00
|
|
|
},
|
|
|
|
ticks: {
|
|
|
|
sampleSize: 5,
|
|
|
|
maxRotation: 50,
|
|
|
|
minRotation: 50,
|
2019-01-21 22:17:04 +08:00
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
_resetChart() {
|
2021-11-16 17:26:26 +08:00
|
|
|
this._chart?.destroy();
|
|
|
|
this._chart = null;
|
2019-01-21 22:17:04 +08:00
|
|
|
},
|
|
|
|
});
|