Vue 3 chart fixes.

This commit is contained in:
Buster Neece 2022-12-12 11:51:53 -06:00
parent 79e7ed7eb3
commit 2fdc52691e
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
8 changed files with 236 additions and 229 deletions

View File

@ -6,7 +6,7 @@
<translate key="lang_title">Audit Log</translate>
</h2>
<div class="flex-shrink">
<date-range-dropdown v-model:date-range="dateRange" @update="relist"></date-range-dropdown>
<date-range-dropdown v-model="dateRange" @update="relist"></date-range-dropdown>
</div>
</div>
</div>

View File

@ -1,18 +1,29 @@
<template>
<a :href="src" class="album-art" target="_blank" data-fancybox="gallery">
<b-img class="album_art" :src="src" loading="lazy"
:style="{ width: this.width+'px', height: 'auto', 'border-radius': '5px' }"></b-img>
<a v-if="src" :href="src" class="album-art" target="_blank" data-fancybox="gallery">
<img class="album_art" :src="src" loading="lazy" alt="">
</a>
</template>
<script>
export default {
props: {
src: String,
width: {
type: Number,
default: 40
}
<style scoped>
img.album_art {
width: v-bind(widthPx);
height: auto;
border-radius: 5px;
}
</style>
<script setup>
import {computed} from "vue";
const props = defineProps({
src: String,
width: {
type: Number,
default: 40
}
};
});
const widthPx = computed(() => {
return props.width + 'px';
});
</script>

View File

@ -1,7 +1,8 @@
<template>
<date-range-picker
v-bind="$props" ref="picker" controlContainerClass="" opens="left" show-dropdowns
:time-picker-increment="1" :ranges="ranges" :date-range="modelValue" @update="onUpdate">
:time-picker-increment="1" :ranges="ranges" v-model="dateRange" v-model:date-range="dateRange"
@select="onSelect">
<template #input="datePicker">
<a class="btn btn-bg dropdown-toggle" id="reportrange" href="#" @click.prevent="">
<icon icon="date_range"></icon>
@ -16,7 +17,7 @@
</template>
<style lang="scss">
@import '../../../node_modules/vue3-daterange-picker/src/assets/daterangepicker';
@import 'vue3-daterange-picker/src/assets/daterangepicker';
</style>
<script>
@ -28,6 +29,11 @@ export default {
name: 'DateRangeDropdown',
components: {DateRangePicker, Icon},
emits: ['update:modelValue', 'update'],
inheritAttrs: false,
model: {
prop: 'modelValue',
event: 'update:modelValue'
},
props: {
tz: {
type: String,
@ -50,8 +56,7 @@ export default {
default: false,
},
modelValue: {
type: [Object],
default: null,
type: Object,
required: true
},
customRanges: {
@ -60,6 +65,14 @@ export default {
},
},
computed: {
dateRange: {
get() {
return this.modelValue;
},
set(newValue) {
// Noop
}
},
ranges() {
let ranges = {};
@ -107,9 +120,9 @@ export default {
}
},
methods: {
onUpdate(newValue) {
this.$emit('update:modelValue', newValue);
this.$emit('update', newValue);
onSelect(range) {
this.$emit('update:modelValue', range);
this.$emit('update', range);
}
}
}

View File

@ -4,60 +4,54 @@
</canvas>
</template>
<script>
import _ from 'lodash';
import {Chart} from 'chart.js';
import {Tableau20} from '~/vendor/chartjs-colorschemes/colorschemes.tableau.js';
<script setup>
import {get, templateRef, watchOnce} from "@vueuse/core";
import {Tableau20} from "~/vendor/chartjs-colorschemes/colorschemes.tableau";
import {Chart} from "chart.js";
import {onUnmounted} from "vue";
export default {
name: 'PieChart',
inheritAttrs: true,
props: {
options: Object,
data: Array,
labels: Array,
aspectRatio: {
type: Number,
default: 2
}
},
data() {
return {
_chart: null
};
},
mounted() {
this.renderChart();
},
methods: {
renderChart() {
const defaultOptions = {
type: 'pie',
data: {
labels: this.labels,
datasets: this.data
},
options: {
aspectRatio: this.aspectRatio,
plugins: {
colorschemes: {
scheme: Tableau20
}
}
}
};
if (this._chart)
this._chart.destroy();
let chartOptions = _.defaultsDeep({}, this.options, defaultOptions);
this._chart = new Chart(this.$refs.canvas.getContext('2d'), chartOptions);
}
},
beforeDestroy() {
if (this._chart) {
this._chart.destroy();
}
const props = defineProps({
options: Object,
data: Array,
labels: Array,
aspectRatio: {
type: Number,
default: 2
}
};
});
const $canvas = templateRef('canvas');
let $chart = null;
watchOnce($canvas, () => {
const defaultOptions = {
type: 'pie',
data: {
labels: props.labels,
datasets: props.data
},
options: {
aspectRatio: props.aspectRatio,
plugins: {
colorschemes: {
scheme: Tableau20
}
}
}
};
if ($chart) {
$chart.destroy();
}
let chartOptions = _.defaultsDeep({}, props.options, defaultOptions);
$chart = new Chart(get($canvas).getContext('2d'), chartOptions);
});
onUnmounted(() => {
if ($chart) {
$chart.destroy();
}
});
</script>

View File

@ -4,103 +4,100 @@
</canvas>
</template>
<script>
import _ from 'lodash';
<script setup>
import {get, templateRef, watchOnce} from "@vueuse/core";
import {Tableau20} from "~/vendor/chartjs-colorschemes/colorschemes.tableau";
import {DateTime} from "luxon";
import {Chart} from 'chart.js';
import _ from "lodash";
import {Chart} from "chart.js";
import {onUnmounted} from "vue";
import gettext from "~/vendor/gettext";
import {Tableau20} from '~/vendor/chartjs-colorschemes/colorschemes.tableau.js';
const props = defineProps({
options: Object,
data: Array
});
export default {
name: 'TimeSeriesChart',
inheritAttrs: true,
props: {
options: Object,
data: Array
},
data() {
return {
_chart: null
};
},
mounted () {
this.renderChart();
},
methods: {
renderChart () {
const defaultOptions = {
type: 'line',
data: {
datasets: this.data
const $canvas = templateRef('canvas');
let $chart = null;
const {$gettext} = gettext;
watchOnce($canvas, () => {
const defaultOptions = {
type: 'line',
data: {
datasets: props.data
},
options: {
aspectRatio: 3,
plugins: {
zoom: {
// Container for pan options
pan: {
enabled: true,
mode: 'x'
}
},
options: {
aspectRatio: 3,
plugins: {
zoom: {
// Container for pan options
pan: {
enabled: true,
mode: 'x'
}
},
colorschemes: {
scheme: Tableau20
}
colorschemes: {
scheme: Tableau20
}
},
scales: {
x: {
type: 'time',
distribution: 'linear',
display: true,
min: DateTime.now().minus({days: 30}).toJSDate(),
max: DateTime.now().toJSDate(),
time: {
unit: 'day',
tooltipFormat: DateTime.DATE_SHORT,
},
scales: {
x: {
type: 'time',
distribution: 'linear',
display: true,
min: DateTime.now().minus({days: 30}).toJSDate(),
max: DateTime.now().toJSDate(),
time: {
unit: 'day',
tooltipFormat: DateTime.DATE_SHORT,
},
ticks: {
source: 'data',
autoSkip: true
}
},
y: {
display: true,
scaleLabel: {
display: true,
labelString: this.$gettext('Listeners')
},
ticks: {
min: 0
}
}
ticks: {
source: 'data',
autoSkip: true
}
},
y: {
display: true,
scaleLabel: {
display: true,
labelString: $gettext('Listeners')
},
tooltips: {
intersect: false,
mode: 'index',
callbacks: {
label: function (tooltipItem, myData) {
let label = myData.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += parseFloat(tooltipItem.value).toFixed(2);
return label;
}
}
ticks: {
min: 0
}
}
};
if (this._chart) this._chart.destroy();
let chartOptions = _.defaultsDeep({}, this.options, defaultOptions);
this._chart = new Chart(this.$refs.canvas.getContext('2d'), chartOptions);
}
},
beforeDestroy () {
if (this._chart) {
this._chart.destroy();
},
tooltips: {
intersect: false,
mode: 'index',
callbacks: {
label: function (tooltipItem, myData) {
let label = myData.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += parseFloat(tooltipItem.value).toFixed(2);
return label;
}
}
}
}
};
if ($chart) {
$chart.destroy();
}
};
let chartOptions = _.defaultsDeep({}, props.options, defaultOptions);
$chart = new Chart(get($canvas).getContext('2d'), chartOptions);
});
onUnmounted(() => {
if ($chart) {
$chart.destroy();
}
});
</script>

View File

@ -312,7 +312,7 @@ export default {
window.addEventListener('hashchange', this.onHashChange);
},
destroyed() {
unmounted() {
window.removeEventListener('hashchange', this.onHashChange);
},
computed: {

View File

@ -1,5 +0,0 @@
<template>
<slot/>
</template>
<script setup></script>

View File

@ -4,71 +4,68 @@
</canvas>
</template>
<script>
import {Chart} from 'chart.js';
import {Tableau20} from '~/vendor/chartjs-colorschemes/colorschemes.tableau.js';
<script setup>
import {get, templateRef, watchOnce} from "@vueuse/core";
import {Tableau20} from "~/vendor/chartjs-colorschemes/colorschemes.tableau";
import {Chart} from "chart.js";
import gettext from "~/vendor/gettext";
import {onUnmounted} from "vue";
export default {
name: 'HourChart',
inheritAttrs: true,
props: {
options: Object,
data: Array,
labels: Array
},
data() {
return {
_chart: null
};
},
mounted() {
this.renderChart();
},
methods: {
renderChart() {
const defaultOptions = {
type: 'bar',
data: {
labels: this.labels,
datasets: this.data
const props = defineProps({
options: Object,
data: Array,
labels: Array
});
let $chart = null;
const $canvas = templateRef('canvas');
const {$gettext} = gettext;
watchOnce($canvas, () => {
const defaultOptions = {
type: 'bar',
data: {
labels: props.labels,
datasets: props.data
},
options: {
aspectRatio: 2,
plugins: {
colorschemes: {
scheme: Tableau20
}
},
scales: {
x: {
scaleLabel: {
display: true,
labelString: $gettext('Hour')
}
},
options: {
aspectRatio: 2,
plugins: {
colorschemes: {
scheme: Tableau20
}
y: {
scaleLabel: {
display: true,
labelString: $gettext('Listeners')
},
scales: {
x: {
scaleLabel: {
display: true,
labelString: this.$gettext('Hour')
}
},
y: {
scaleLabel: {
display: true,
labelString: this.$gettext('Listeners')
},
ticks: {
min: 0
}
}
ticks: {
min: 0
}
}
};
if (this._chart) this._chart.destroy();
let chartOptions = _.defaultsDeep({}, this.options, defaultOptions);
this._chart = new Chart(this.$refs.canvas.getContext('2d'), chartOptions);
}
},
beforeDestroy() {
if (this._chart) {
this._chart.destroy();
}
}
};
if ($chart) {
$chart.destroy();
}
};
let chartOptions = _.defaultsDeep({}, props.options, defaultOptions);
$chart = new Chart(get($canvas).getContext('2d'), chartOptions);
});
onUnmounted(() => {
if ($chart) {
$chart.destroy();
}
});
</script>