[update] add chart series

This commit is contained in:
peterlu14
2023-01-31 10:37:06 +08:00
parent 9000fabdea
commit ef8ce2a0c4
11 changed files with 208 additions and 126 deletions
+1
View File
@@ -22,6 +22,7 @@ module.exports = {
],
rules: {
'@typescript-eslint/no-empty-interface': 0,
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'prettier/prettier': ['warn', {}, { usePrettierrc: true }],
@@ -1,5 +1,5 @@
<template>
<va-card class="h-200px overflow-auto">
<va-card>
<va-card-content>
<va-button @click="showModal">FILE</va-button>
<p>X: {{ channelStore.xAxisSelected.name }} Y: {{ channelStore.yAxisSelected.name }}</p>
@@ -18,7 +18,7 @@
</template>
</va-list>
<Suspense>
<FileModal ref="file_modal_ref"></FileModal>
<FileView ref="file_modal_ref"></FileView>
</Suspense>
</va-card-content>
</va-card>
@@ -28,14 +28,14 @@
import { ref, reactive } from 'vue'
import { useChannelStore } from '@/stores/data-analysis/channel'
import { useFileViewStore } from '@/stores/data-analysis/file-view'
import FileModal from '@/components/data-analysis/FileModal.vue'
import FileView from '@/components/data-analysis/FileView.vue'
const channelStore = useChannelStore()
const fileViewStore = useFileViewStore()
const selectedFiles = reactive(fileViewStore.filesSelected)
/* File Modal Handling */
let file_modal_ref = ref<InstanceType<typeof FileModal> | null>(null)
let file_modal_ref = ref<InstanceType<typeof FileView> | null>(null)
const showModal = function () {
file_modal_ref.value?.showModal()
}
@@ -2,8 +2,6 @@
<slideout v-model="showSlideOut" title="The title" :size="'120%'" dock="left" resizable>
<ChannelSelector></ChannelSelector>
<div class="pa-1 d-flex align-center">
<!-- <va-input v-model="filter" placeholder="Filter..." class="mr-3" style="flex: 0 200px" clearable />
<va-checkbox v-model="isFilterCaseSensitive" class="mr-3" label="Case sensitive" /> -->
<va-button-group class="mr-1">
<va-button @click="changeViewFormat(0)">Table</va-button>
<va-button disabled @click="changeViewFormat(1)">Tree</va-button>
@@ -21,24 +19,34 @@
<!-- <div v-if="loading">Loading...</div> -->
<va-inner-loading :loading="loading">
<div>
<TableFormat v-if="viewFormat === 0" ref="table_format_ref" :columns="columns" :rows="rows"></TableFormat>
<TableFormat
v-if="viewFormat === 0"
ref="table_format_ref"
:columns="columns"
:rows="rows"
@on-select="onSelect"
></TableFormat>
<TreeFormat v-if="viewFormat === 1" ref="table_format_ref" :columns="columns" :rows="rows"></TreeFormat>
</div>
</va-inner-loading>
</slideout>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ref, reactive, onMounted } from 'vue'
import { useFileViewStore } from '@/stores/data-analysis/file-view'
import { useChannelStore } from '@/stores/data-analysis/channel'
import { MetaFile } from '@/utils/file'
import TableFormat from './TableFormat.vue'
import TreeFormat from './TreeFormat.vue'
import ChannelSelector from './ChannelSelector.vue'
import configTable from '@/data/config-table'
const table_format_ref = ref<InstanceType<typeof TableFormat> | null>(null)
const fileViewStore = useFileViewStore()
const channelStore = useChannelStore()
const fileView = reactive(fileViewStore.fileView)
const table_format_ref = ref<InstanceType<typeof TableFormat> | null>(null)
const rows: any = fileView.children
fileView.appendChildren()
const columns = reactive([
{
label: 'Name',
@@ -60,32 +68,10 @@
const showSlideOut = ref(false)
const showModal = function () {
showSlideOut.value = !showSlideOut.value
// initLoad()
console.log('fileView', fileView.getChildren())
console.log('rows', rows)
setTimeout(() => {
loading.value = false
}, 1500)
}
const initLoad = async function () {
// rows.length = 0
// rows.push(...fileView.getChildren())
// if (rows.length < fileView.children.length) {
// rows.push(...fileView.children.slice(rows.length, fileView.children.length - 1))
// }
// for (const index in rows) {
// console.log(index, rows[index].children.length, fileView.children[index].children.length)
// if (rows[index].children.length < fileView.children[index].children.length) {
// rows[index].children.push(
// ...fileView.children[index].children.slice(
// rows[index].children.length,
// fileView.children[index].children.length - 1,
// ),
// )
// }
// }
}, 500)
}
const viewFormat = ref(0)
@@ -96,7 +82,6 @@
const changeFileView = async function (view: string) {
fileView.changeView(view)
await fileView.appendChildren(1)
// initLoad()
}
const expandAll = function (expandOrNot: boolean) {
@@ -104,6 +89,32 @@
if (expandOrNot === false) table_format_ref.value?.collapseAll()
}
const onSelect = function (selectedFile: MetaFile[]) {
fileViewStore.filesSelected.length = 0
fileViewStore.filesSelected.push(...selectedFile)
if (fileViewStore.filesSelected.length > 0) {
// TODO get all selected library
const config: any = configTable.getModeConfig(
fileViewStore.filesSelected[0].device.library_name,
fileViewStore.filesSelected[0].parameter.MODE,
)
const channel = Object.values(config.channels)
const channelOptions = channel.map((v: any, idx) => {
v.id = idx
return v
})
channelStore.xAxisOptions.length = 0
channelStore.xAxisOptions.push(...channelOptions)
channelStore.yAxisOptions.length = 0
channelStore.yAxisOptions.push(...channelOptions)
}
}
onMounted(() => {
fileView.appendChildren()
})
defineExpose({
showModal,
})
@@ -2,18 +2,27 @@
<div>
<va-card class="h-full">
<va-card-content class="h-full w-full">
<EChart ref="chart_ref" :option="option" :autoresize="true" :loading="loading" />
<EChart ref="chart_ref" :option="chart" :autoresize="true" :loading="loading" />
</va-card-content>
</va-card>
</div>
</template>
<script setup lang="ts">
import LineChart from '@/data/echart/composables/LineChart'
import { EChartsCoreOption } from 'echarts'
import { ref } from 'vue'
import { ECharts, EChartsCoreOption } from 'echarts'
import { ref, reactive, watch } from 'vue'
import { useFileViewStore } from '@/stores/data-analysis/file-view'
import { MetaFile } from '@/utils/file'
const loading = ref(false)
const { chart_ref, option } = LineChart()
const props = defineProps({
chart: {
type: Object,
default: () => {
return {}
},
},
})
const chart_ref = ref<ECharts | null>(null)
const setOption = function (option: EChartsCoreOption) {
chart_ref.value?.setOption(option)
@@ -44,14 +53,37 @@
})
}
// Loading
const loading = ref(false)
const startLoading = function () {
loading.value = true
}
const stopLoading = function () {
loading.value = false
}
// change when file selected
const fileViewStore = useFileViewStore()
const fileSelected = reactive(fileViewStore.filesSelected)
const selectionSave: never | MetaFile[] = reactive([])
watch(
fileSelected,
(data) => {
const unSelectFiles = selectionSave.filter((ele) => data.findIndex((ele2) => ele.id === ele2.id) === -1)
for (const meta of unSelectFiles) {
props.chart.seriesManager.delSeries({ id: meta.id, name: meta.name })
}
selectionSave.length = 0
selectionSave.push(...data)
for (const meta of data) {
props.chart.seriesManager.addSeries({ id: meta.id, name: meta.name })
}
chart_ref.value?.setOption(props.chart, true)
},
{ deep: true },
)
defineExpose({
startLoading,
stopLoading,
+13 -31
View File
@@ -10,17 +10,19 @@
collapsable: true,
rowKey: 'id',
}"
@selected-rows-change="selectionChanged"
@selected-rows-change="select"
>
</VueGoodTable>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, watchEffect, toRef } from 'vue'
import { useFileViewStore } from '@/stores/data-analysis/file-view'
import { useChannelStore } from '@/stores/data-analysis/channel'
import configTable from '@/data/config-table/index'
import { ref, onMounted } from 'vue'
import { MetaFile } from '@/utils/file'
const props = defineProps({
// emit
const emit = defineEmits(['onSelect'])
// props
defineProps({
columns: {
type: Array,
default: () => {
@@ -35,10 +37,8 @@
},
})
const fileViewStore = useFileViewStore()
const channelStore = useChannelStore()
// ref
const vue_good_table_refs = ref()
// const vue_good_table_refs = ref<InstanceType<typeof VueGoodTable> | null>(null)
const expandAll = function () {
vue_good_table_refs.value.expandAll()
@@ -46,37 +46,19 @@
const collapseAll = function () {
vue_good_table_refs.value.collapseAll()
}
const selectionChanged = function (params: any) {
fileViewStore.filesSelected.length = 0
fileViewStore.filesSelected.push(...params.selectedRows)
if (fileViewStore.filesSelected.length > 0) {
const config: any = configTable.getModeConfig(
fileViewStore.filesSelected[0].device.library_name,
fileViewStore.filesSelected[0].parameter.MODE,
)
const channel = Object.values(config.channels)
const channelOptions = channel.map((v: any, idx) => {
v.id = idx
return v
})
channelStore.xAxisOptions.length = 0
channelStore.xAxisOptions.push(...channelOptions)
channelStore.yAxisOptions.length = 0
channelStore.yAxisOptions.push(...channelOptions)
}
console.log('vue_good_table_refs.value', vue_good_table_refs.value)
const select = function (params: { selectedRows: MetaFile[] }) {
emit('onSelect', params.selectedRows)
}
onMounted(() => {
// Due to "vue_good_table" package error, need to fix group select by reassign function
vue_good_table_refs.value.toggleSelectGroup = function (event: { checked: any }, headerRow: { children: any[] }) {
console.log(event, headerRow)
headerRow.children.forEach((row: { [x: string]: any }) => {
row['vgtSelected'] = event.checked
})
}
})
defineExpose({ selectionChanged, expandAll, collapseAll })
defineExpose({ expandAll, collapseAll })
</script>
<style></style>
+58 -44
View File
@@ -2,13 +2,15 @@
<div class="h-[88vh] grid grid-cols-3 gap-6">
<div class="h-full col-span-1">
<div class="h-1/3">
<FileContainer class="h-9/10"></FileContainer>
<FileContainer class="h-225px overflow-auto"></FileContainer>
</div>
<div class="h-2/3">
<ControlPanel class="h-9/10" @filter-data="filterData"></ControlPanel>
<ControlPanel class="h-[100%]" @filter-data="filterData"></ControlPanel>
</div>
</div>
<LineChartContainer ref="linechart_ref" class="h-[50%] col-span-2"></LineChartContainer>
<template v-for="chart in chartManager.children" :key="chart.id">
<LineChartContainer ref="linechart_ref" :chart="chart" class="h-[100%] col-span-2"></LineChartContainer>
</template>
</div>
</template>
@@ -17,7 +19,11 @@
import FileContainer from '@/components/data-analysis/FileContainer.vue'
import ControlPanel from '@/components/data-analysis/ControlPanel.vue'
import LineChartContainer from '@/components/data-analysis/LineChartContainer.vue'
import { onMounted, ref } from 'vue'
import { useChartStore } from '@/stores/data-analysis/chart'
import { ref, reactive, onMounted } from 'vue'
// reference
const linechart_ref = ref()
// mqtt init
const { startMqtt, publish } = useMqtt()
@@ -25,9 +31,48 @@
// define subscribe and callback
startMqtt(`${controllerID}/data_analysis/#`, (topic: string, message: ArrayBuffer) => {
// [data, data, ceiling, ground]
// [metaID, xData, yData, horizontalLine, twoPointLine]
const msg = JSON.parse(message.toString())
console.log('msg', msg)
// reformat data
for (const info of msg) {
const metaID = info[0]
const xData = info[1]
const yData = info[2]
const horizontal = info[3]
const line = info[4]
const groupData = []
for (let i = 0; i < xData.length; i++) {
groupData.push([xData[i], yData[i]])
}
for (const chart of chartManager.children) {
const seriesIndex = chart.seriesManager.findSeries({ id: metaID })
// append Data
if (seriesIndex !== -1) {
linechart_ref.value[0]?.appendData(seriesIndex, groupData)
}
// draw line
let yAxis_list = horizontal.map((x: any) => ({ yAxis: x }))
let coord_list = [{ coord: [line[0][0], line[0][1]] }, { coord: [line[1][0], line[1][1]] }]
yAxis_list.push(coord_list)
linechart_ref.value[0].setOption({
series: [
{
markLine: {
data: yAxis_list,
},
},
],
})
}
}
// stop loading
linechart_ref.value[0]?.stopLoading()
// download file
const name = 'test'
const url = `http://192.168.2.1:3000/api/analysis/get/csv?name=${name}`
const a = document.createElement('a')
@@ -36,52 +81,21 @@
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
// try draw line
// msg.push(1500000, -1500000)
// reformat data
const _msg = []
for (let i = 0; i < msg[0].length; i++) {
_msg.push([msg[0][i], msg[1][i]])
}
// append Data
linechart_ref.value?.appendData(0, _msg)
// stop loading
linechart_ref.value?.stopLoading()
// draw line
// draw line
if (msg.length < 3) return true
let yAxis_list = msg[2].map((x: any) => ({ yAxis: x }))
let coord_list = [{ coord: [msg[3][0][0], msg[3][0][1]] }, { coord: [msg[3][1][0], msg[3][1][1]] }]
// yAxis_list.append([{ coord:[ msg[3][0][0],msg[3][0][1]]},{ coord:[ msg[3][1][0], msg[3][1][1]]}])
yAxis_list.push(coord_list)
console.log('yAxis_list', yAxis_list)
linechart_ref.value.setOption({
series: [
{
markLine: {
data: yAxis_list,
},
},
],
})
})
// reference
const linechart_ref = ref()
// ControlPanel handling
const filterData = function (e: any) {
linechart_ref.value?.startLoading()
console.log(linechart_ref)
console.log(e)
linechart_ref.value[0]?.startLoading()
publish(`${controllerID}_data_analysis/get_analysis_data`, JSON.stringify({ e }))
}
const chartStore = useChartStore()
const chartManager = reactive(chartStore.chart)
onMounted(() => {
if (chartManager.children.length === 0) {
chartManager.addChart()
}
})
defineExpose({ linechart_ref, filterData })
</script>
+12
View File
@@ -0,0 +1,12 @@
import ChartManager from '@/utils/chart/chartManager'
import { defineStore } from 'pinia'
export const useChartStore = defineStore('data-analysis-chart', {
state: () => ({
chart: new ChartManager(),
}),
// could also be defined as
// state: () => ({ count: 0 })
getters: {},
actions: {},
})
+4 -1
View File
@@ -10,7 +10,10 @@ class Series {
this.data = []
this.silent = false
this.animation = false
this.markLine = {}
this.markLine = {
symbol: ['none', 'none'],
data: [],
}
}
setOption(options: seriesOption) {
+5 -3
View File
@@ -8,8 +8,10 @@ class SeriesManager {
}
addSeries(option: seriesOption) {
const newSeries = new Series(option)
this.children.push(newSeries)
if (this.findSeries(option) === -1) {
const newSeries = new Series(option)
this.children.push(newSeries)
}
}
getSeries(target: seriesTarget): Series | Series[] {
@@ -39,7 +41,7 @@ class SeriesManager {
delSeries(target: seriesTarget) {
const deleteIdx = this.findSeries(target)
if (deleteIdx) {
if (deleteIdx !== undefined) {
this.children.splice(deleteIdx, 1)
return true
}
+6 -6
View File
@@ -13,21 +13,21 @@ class Chart {
legend: any
// tooltip: any
// grid: any
// dataZoom: any
dataZoom: any
seriesManager: SeriesManager
series: any
// gridManager: GridManager
constructor() {
this.title = { text: 'Gradient along the y axis' }
// this.title = { text: 'Gradient along the y axis' }
this.seriesManager = new SeriesManager()
// this.gridManager = new GridManager()
this.legend = {}
this.legend = { type: 'scroll' }
// this.tooltip = new Tooltip()
this.xAxis = {}
this.yAxis = {}
this.xAxis = { scale: true }
this.yAxis = { scale: true }
// this.grid = this.gridManager.getGrid()
this.series = this.seriesManager.getSeries({})
// this.dataZoom = [{}]
this.dataZoom = [{ type: 'inside' }, { type: 'slider' }]
}
}
+25
View File
@@ -0,0 +1,25 @@
import Chart from './chart'
class ChartManager {
children: Chart[]
constructor() {
this.children = []
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
addChart(idx?: number) {
const newChart = new Chart()
this.children.push(newChart)
}
switchChart() {
return
}
clearChart() {
return
}
delChart() {
return
}
}
export default ChartManager