mirror of
https://github.com/knadh/listmonk.git
synced 2025-10-11 15:57:08 +08:00
Fix broken chart components.
This commit is contained in:
parent
2feb1b0fb8
commit
b946c33e61
3 changed files with 206 additions and 0 deletions
48
frontend/src/components/BarChart.vue
Normal file
48
frontend/src/components/BarChart.vue
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<section class="bar-chart">
|
||||||
|
<canvas class="bar-chart-canvas" />
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Chart from 'chart.js/auto';
|
||||||
|
|
||||||
|
const DEFAULT = {
|
||||||
|
type: 'bar',
|
||||||
|
data: {},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
indexAxis: 'y',
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderColor: '#ddd',
|
||||||
|
borderWidth: 1,
|
||||||
|
titleColor: '#666',
|
||||||
|
bodyColor: '#666',
|
||||||
|
bodyFont: {
|
||||||
|
size: 15,
|
||||||
|
},
|
||||||
|
bodySpacing: 10,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'BarChart',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
data: { type: Object, default: () => { } },
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
const ctx = this.$el.querySelector('.bar-chart-canvas');
|
||||||
|
this.chart = new Chart(ctx, { ...DEFAULT, data: this.$props.data });
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
155
frontend/src/components/Chart.vue
Normal file
155
frontend/src/components/Chart.vue
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<section class="chart">
|
||||||
|
<canvas class="chart-canvas" />
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Chart from 'chart.js/auto';
|
||||||
|
|
||||||
|
const DEFAULT_DONUT = {
|
||||||
|
type: 'doughnut',
|
||||||
|
data: {},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
cutout: '70%',
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderColor: '#ddd',
|
||||||
|
borderWidth: 1,
|
||||||
|
titleColor: '#666',
|
||||||
|
bodyColor: '#666',
|
||||||
|
bodyFont: {
|
||||||
|
size: 15,
|
||||||
|
},
|
||||||
|
bodySpacing: 10,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_LINE = {
|
||||||
|
type: 'line',
|
||||||
|
data: {},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
lineTension: 0.5,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
interaction: {
|
||||||
|
intersect: false,
|
||||||
|
axis: 'index',
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderColor: '#ddd',
|
||||||
|
borderWidth: 1,
|
||||||
|
bodyColor: '#666',
|
||||||
|
displayColors: true,
|
||||||
|
bodyFont: {
|
||||||
|
size: 15,
|
||||||
|
},
|
||||||
|
bodySpacing: 10,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
grid: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
grid: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
precision: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_BAR = {
|
||||||
|
type: 'bar',
|
||||||
|
data: {},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
indexAxis: 'y',
|
||||||
|
barThickness: 40,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderColor: '#ddd',
|
||||||
|
borderWidth: 1,
|
||||||
|
titleColor: '#666',
|
||||||
|
bodyColor: '#666',
|
||||||
|
bodyFont: {
|
||||||
|
size: 15,
|
||||||
|
},
|
||||||
|
bodySpacing: 10,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
grid: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
grid: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Chart',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
data: { type: Object, default: () => { } },
|
||||||
|
type: { type: String, default: 'line' },
|
||||||
|
onClick: { type: Function, default: () => { } },
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
const ctx = this.$el.querySelector('.chart-canvas');
|
||||||
|
|
||||||
|
let def = {};
|
||||||
|
switch (this.$props.type) {
|
||||||
|
case 'donut':
|
||||||
|
def = DEFAULT_DONUT;
|
||||||
|
break;
|
||||||
|
case 'bar':
|
||||||
|
def = DEFAULT_BAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
def = DEFAULT_LINE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const conf = { ...def, data: this.$props.data };
|
||||||
|
if (this.$props.onClick) {
|
||||||
|
conf.options.onClick = this.$props.onClick;
|
||||||
|
}
|
||||||
|
this.chart = new Chart(ctx, conf);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -169,6 +169,9 @@ export default Vue.extend({
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
makeChart(data) {
|
makeChart(data) {
|
||||||
|
if (data.length === 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
labels: data.map((d) => dayjs(d.date).format('DD MMM')),
|
labels: data.map((d) => dayjs(d.date).format('DD MMM')),
|
||||||
datasets: [
|
datasets: [
|
||||||
|
|
Loading…
Add table
Reference in a new issue