WIP #300 Performance page done. Use ref() instead of reactive() in independant Vue3 component.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<Chart type="line" :data="freqChartData" :options="freqChartOptions" class="h-96" />
|
<Chart type="line" :data="primeVueSetDataState" :options="primeVueSetOptionsState" class="h-96" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -19,51 +19,23 @@ const cloneDeep = (obj) => JSON.parse(JSON.stringify(obj));
|
|||||||
// 試著把 chart 獨立成一個 vue component
|
// 試著把 chart 獨立成一個 vue component
|
||||||
// 企圖防止 PrimeVue 誤用其他圖表 option 值的 bug
|
// 企圖防止 PrimeVue 誤用其他圖表 option 值的 bug
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
props: {
|
||||||
|
chartData: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
yUnit: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
const performanceStore = usePerformanceStore();
|
const performanceStore = usePerformanceStore();
|
||||||
|
|
||||||
const freqChartData = computed(() => performanceStore.freqChartData);
|
|
||||||
const originalFreqChartOptions = computed(() => performanceStore.freqChartOptions);
|
|
||||||
const minX = computed(() => performanceStore.freqChartXData.minX);
|
|
||||||
const maxX = computed(() => performanceStore.freqChartXData.maxX);
|
|
||||||
const xData = computed(() => performanceStore.freqChartXData.xData);
|
|
||||||
const content = computed(() => performanceStore.freqChartXData.content);
|
|
||||||
const customizedScaleOption = computed(() => {});
|
const customizedScaleOption = computed(() => {});
|
||||||
|
const primeVueSetDataState = ref(null);
|
||||||
const updatedFreqChartOptions = ref(cloneDeep(originalFreqChartOptions.value));
|
const primeVueSetOptionsState = ref(null);
|
||||||
|
|
||||||
const customizeOptionsFunc = () => {
|
|
||||||
// Customize X axis ticks due to different differences between min and max of data group
|
|
||||||
// Compare page and Performance page share the same logic
|
|
||||||
const formatToSet = setTimeStringFormatBaseOnTimeDifference(minX.value, maxX.value);
|
|
||||||
const ticksOfXAxis = mapTimestampToAxisTicksByFormat(xData.value, formatToSet);
|
|
||||||
|
|
||||||
|
|
||||||
customizedScaleOption.value = getCustomizedScaleOption(
|
|
||||||
knownScaleLineChartOptions, {
|
|
||||||
customizeOptions: {
|
|
||||||
content, ticksOfXAxis,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const newTicksCallback = (value, index, values) => {
|
|
||||||
return value; // 沒有單位,只有數值,因為是取計算數量
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateTicksCallback = () => {
|
|
||||||
|
|
||||||
//在這裡額外宣告本圖表的 callback, 區分跟其他圖表的 callback,避免共用 option 造成不預期的共用與混淆
|
|
||||||
if (updatedFreqChartOptions.value.scales && updatedFreqChartOptions.value.scales.y) {
|
|
||||||
updatedFreqChartOptions.value = customizedScaleOption;
|
|
||||||
updatedFreqChartOptions.value.scales.y.ticks.callback = newTicksCallback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(originalFreqChartOptions, (newOptions) => {
|
|
||||||
updatedFreqChartOptions.value = cloneDeep(newOptions);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare page and Performance have this same function.
|
* Compare page and Performance have this same function.
|
||||||
@@ -102,7 +74,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Compare page and Performance have this same function.
|
/** Compare page and Performance have this same function.
|
||||||
@@ -140,14 +112,91 @@ export default {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getLineChartPrimeVueSetting = (chartData, content) => {
|
||||||
|
let datasets;
|
||||||
|
let minX = chartData?.x_axis?.min;
|
||||||
|
let maxX = chartData?.x_axis?.max;
|
||||||
|
let maxY = chartData?.y_axis?.max;
|
||||||
|
let xData;
|
||||||
|
let primeVueSetData = {};
|
||||||
|
let primeVueSetOption = {};
|
||||||
|
const getMoment = (time)=> {
|
||||||
|
return this.$moment(time).format('YYYY/M/D hh:mm:ss')
|
||||||
|
};
|
||||||
|
|
||||||
|
datasets = chartData.data;
|
||||||
|
xData = chartData.data.map(item => new Date(item.x).getTime());
|
||||||
|
|
||||||
|
// Customize X axis ticks due to different differences between min and max of data group
|
||||||
|
// Compare page and Performance page share the same logic
|
||||||
|
const formatToSet = setTimeStringFormatBaseOnTimeDifference(minX, maxX);
|
||||||
|
const ticksOfXAxis = mapTimestampToAxisTicksByFormat(xData, formatToSet);
|
||||||
|
const customizedScaleOption = getCustomizedScaleOption(
|
||||||
|
knownScaleLineChartOptions, {
|
||||||
|
customizeOptions: {
|
||||||
|
content, ticksOfXAxis,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
primeVueSetData = {
|
||||||
|
labels: xData,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: content.title,
|
||||||
|
data: datasets,
|
||||||
|
fill: false,
|
||||||
|
tension: 0, // 貝茲曲線張力
|
||||||
|
borderColor: '#0099FF',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
primeVueSetOption = {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
layout: {
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: false, // 圖例
|
||||||
|
tooltip: {
|
||||||
|
displayColors: false,
|
||||||
|
titleFont: {weight: 'normal'},
|
||||||
|
callbacks: {
|
||||||
|
title: function(context) {
|
||||||
|
return `${content.x}: ${getMoment(context[0].parsed.x)}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
scales: customizedScaleOption,
|
||||||
|
};
|
||||||
|
|
||||||
|
primeVueSetOption.scales.y.ticks.precision = 0; // y 軸顯示小數點後 0 位
|
||||||
|
primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
|
||||||
|
return `${content.y}: ${context.parsed.y}`;
|
||||||
|
};
|
||||||
|
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
primeVueSetDataState.value = primeVueSetData;
|
||||||
|
primeVueSetOptionsState.value = primeVueSetOption;
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
customizeOptionsFunc();
|
getLineChartPrimeVueSetting(props.chartData, props.content);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
freqChartData,
|
...props,
|
||||||
updatedFreqChartOptions,
|
primeVueSetDataState,
|
||||||
updateTicksCallback,
|
primeVueSetOptionsState,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
<li class="bg-neutral-10 mb-4 p-1 border border-neutral-300 rounded">
|
<li class="bg-neutral-10 mb-4 p-1 border border-neutral-300 rounded">
|
||||||
<span class="block font-bold text-sm leading-loose text-center my-2">{{ contentData.freq.title }}</span>
|
<span class="block font-bold text-sm leading-loose text-center my-2">{{ contentData.freq.title }}</span>
|
||||||
<!-- <Chart type="line" :data="freqData" :options="freqOptions" class="h-96" /> -->
|
<!-- <Chart type="line" :data="freqData" :options="freqOptions" class="h-96" /> -->
|
||||||
<FreqChart/>
|
<FreqChart v-if="performanceData" :chartData="performanceData?.freq?.cases" :content="contentData?.freq" yUnit="count"/>
|
||||||
</li>
|
</li>
|
||||||
<li class="bg-neutral-10 p-1 border border-neutral-300 rounded">
|
<li class="bg-neutral-10 p-1 border border-neutral-300 rounded">
|
||||||
<span class="block font-bold text-sm leading-loose text-center my-2">{{ contentData.casesByTask.title }}</span>
|
<span class="block font-bold text-sm leading-loose text-center my-2">{{ contentData.casesByTask.title }}</span>
|
||||||
@@ -152,8 +152,6 @@ import { simpleTimeLabel, followTimeLabel, dateLabel,
|
|||||||
} from '@/module/timeLabel.js';
|
} from '@/module/timeLabel.js';
|
||||||
import FreqChart from './FreqChart.vue';
|
import FreqChart from './FreqChart.vue';
|
||||||
|
|
||||||
const myCloneDeep = (obj) => JSON.parse(JSON.stringify(obj));
|
|
||||||
|
|
||||||
const knownScaleLineChartOptions = {
|
const knownScaleLineChartOptions = {
|
||||||
x: {
|
x: {
|
||||||
type: 'time',
|
type: 'time',
|
||||||
@@ -219,7 +217,7 @@ export default {
|
|||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
StatusBar,
|
StatusBar,
|
||||||
FreqChart
|
FreqChart,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -341,6 +339,11 @@ export default {
|
|||||||
case 'count': // 次數 10 個點
|
case 'count': // 次數 10 個點
|
||||||
datasets = chartData.data;
|
datasets = chartData.data;
|
||||||
xData = chartData.data.map(item => new Date(item.x).getTime());
|
xData = chartData.data.map(item => new Date(item.x).getTime());
|
||||||
|
|
||||||
|
// special case, freq chart case
|
||||||
|
if(whichCaller === "freqChartCaller") {
|
||||||
|
this.setFreqChartXData({ minX, maxX, xData, content});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,12 +357,7 @@ export default {
|
|||||||
content, ticksOfXAxis,
|
content, ticksOfXAxis,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// special case, freq chart case
|
|
||||||
if(whichCaller === "freqChartCaller") {
|
|
||||||
this.setFreqChartXData({ minX, maxX, xData, content});
|
|
||||||
}
|
|
||||||
|
|
||||||
primeVueSetData = {
|
primeVueSetData = {
|
||||||
labels: xData,
|
labels: xData,
|
||||||
datasets: [
|
datasets: [
|
||||||
@@ -794,10 +792,6 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
[this.avgWaitingTimeByEdgeData, this.avgWaitingTimeByEdgeOptions] = [null, null]
|
[this.avgWaitingTimeByEdgeData, this.avgWaitingTimeByEdgeOptions] = [null, null]
|
||||||
}
|
}
|
||||||
[this.freqData, this.freqOptions] = this.getLineChart(this.performanceData.freq.cases, this.contentData.freq, 'count', "freqChartCaller");
|
|
||||||
|
|
||||||
this.setFreqChartData(this.freqData);
|
|
||||||
this.setFreqChartOptions(this.freqOptions);
|
|
||||||
|
|
||||||
[this.casesByTaskData, this.casesByTaskOptions] = this.getHorizontalBarChart(this.performanceData.freq.cases_by_task,
|
[this.casesByTaskData, this.casesByTaskOptions] = this.getHorizontalBarChart(this.performanceData.freq.cases_by_task,
|
||||||
this.contentData.casesByTask, true, 'count');
|
this.contentData.casesByTask, true, 'count');
|
||||||
|
|||||||
Reference in New Issue
Block a user