Compare commits

...

58 Commits

Author SHA1 Message Date
TommyXin 120553f8c0 replay double markArea 2021-07-01 21:25:06 +08:00
TommyXin e50f2b5efc realtime elite unit 2021-07-01 20:07:34 +08:00
TommyXin c780fd7a57 realtime unit 2021-07-01 19:59:43 +08:00
TommyXin bd298b73bc interval & task config stimulate 2021-07-01 19:40:43 +08:00
TommyXin c3e2f7f6e5 task config 2021-07-01 13:54:26 +08:00
TommyXin c8c1abc2a5 [update] api opt 2021-06-27 23:42:17 +08:00
TommyXin dd5a8bfe27 Merge remote-tracking branch 'origin/master' into opt_ui_1 2021-06-19 11:50:39 +08:00
peterlu14 ac889e5410 Merge remote-tracking branch 'origin/feature/replay' 2021-06-16 02:24:31 +08:00
Jordan Hsu 9584d751fe [update] replay change log scale logic 2021-06-11 22:43:17 +08:00
Jordan Hsu fd31d41bdb [fix] elite cycle bug 2021-06-11 13:09:29 +08:00
peterlu14 9087f6776b Merge remote-tracking branch 'origin/feature/replay' 2021-06-10 18:48:26 +08:00
peterlu14 2cdd14d97d [update] elite download 2021-06-10 18:32:12 +08:00
Jordan Hsu fca7f1a093 [add] filetable delete selected files 2021-06-10 18:03:31 +08:00
Jordan Hsu e63e40caad Merge branch 'master' into feature/replay 2021-06-10 17:22:04 +08:00
peterlu14 68bf3cda73 [fix] elite range parameter mouse leave 2021-06-10 17:18:21 +08:00
Jordan Hsu fed196a0da [fix] elite overview bug 2021-06-10 14:35:44 +08:00
peterlu14 557629fb8c [fix] replay series data wrong index 2021-06-10 14:17:45 +08:00
Jordan Hsu 60f4e0fd10 [add] elite two mode 2021-06-10 10:22:15 +08:00
Jordan Hsu c72a55fd5a change parameter word style 2021-06-09 22:27:37 +08:00
Jordan Hsu da242910f6 [add] elite parameter and update UI layout 2021-06-09 22:02:01 +08:00
Jordan Hsu 3e62775857 remove redundant code 2021-06-09 20:06:42 +08:00
Jordan Hsu 2723d4dbb1 remove redundant code 2021-06-09 18:43:44 +08:00
Jordan Hsu f2b828b8af [add] check if show overview chart and update UI 2021-06-09 18:26:07 +08:00
Jordan Hsu 0954c8a778 [update] elite replay UI and fix change axis bug 2021-06-09 18:05:25 +08:00
Jordan Hsu 61616dead0 [update] change cycle logic and unit ohm default value 2021-06-09 17:58:36 +08:00
peterlu14 e9c339450f [update] y-interval default value 2021-06-09 14:10:03 +08:00
peterlu14 5ef75b972f [update] filename repeat & both button & replay download 2021-06-09 14:05:59 +08:00
Jordan Hsu dccc30df3d [add] change cycle vue 2021-06-09 14:03:39 +08:00
Jordan Hsu 90f78d2c24 [init] elite replay 2021-06-08 22:30:36 +08:00
Jordan Hsu 94c265da5d adjust elite parameter recording cycle min from 0 to 1 2021-06-08 18:29:54 +08:00
peterlu14 df52ad3ff9 Merge remote-tracking branch 'origin/feature/replay' 2021-06-08 17:55:14 +08:00
Jordan Hsu 341035f8c4 [hotfix] neulive UI layout bug 2021-06-08 17:05:19 +08:00
peterlu14 25740a6c82 Merge remote-tracking branch 'origin/feature/aboutPage' 2021-06-08 10:03:20 +08:00
peterlu14 c378dc5749 Merge branch 'feature/download-rebuild' 2021-06-08 10:01:32 +08:00
peterlu14 85be4bb558 Merge remote-tracking branch 'origin/opt_ui_1' 2021-06-08 10:01:24 +08:00
peterlu14 7f18bd4672 Merge remote-tracking branch 'origin/feature/replay' 2021-06-08 10:01:12 +08:00
peterlu14 a88833bf87 [update] file system restruct in vuex 2021-06-08 09:59:04 +08:00
TommyXin 30b4d3c76b [add] x-interval & y-interval 2021-06-07 21:14:56 +08:00
Jordan Hsu 74c58b131f [modify] adjust neulive UI layout 2021-06-07 19:02:02 +08:00
Jordan Hsu 266a227b47 [6/7] neulive replay, only wait for download function 2021-06-07 14:33:31 +08:00
Jordan Hsu 86f965a445 typo 2021-06-07 13:37:11 +08:00
Jordan Hsu 18fa86820d [add] replay toolbox: change scale (linear/log), [fix] small bug 2021-06-06 23:01:58 +08:00
Jordan Hsu c29dded14f [add] change min max panel position and remove redundant code 2021-06-06 09:40:47 +08:00
Jordan Hsu b72977b35f [fix] press button won't recover automatically 2021-06-04 18:08:55 +08:00
Jordan Hsu 7391e0a5a0 [add] neulive sti parameter illustration 2021-06-04 18:07:01 +08:00
Jordan Hsu e1a0d996ad [add] replay toolbox: set min/max and show param and use for neulive replay 2021-06-04 14:22:32 +08:00
Jordan Hsu 2ba5fb2683 [add] replay toolbox and use for neulive replay top panel 2021-06-03 22:57:04 +08:00
TommyXin 671b8ad668 [feature] multiple file replay 2021-06-02 03:11:05 +08:00
TommyXin 0de6d455a0 neulive replay opt 2021-06-02 02:28:07 +08:00
peterlu14 9d4836ee28 [update] sample rate 20K 2021-05-31 13:41:01 +08:00
peterlu14 d49dbfda43 [fix] neulive amp gain wrong index 2021-05-26 02:40:43 +08:00
peterlu14 73edf21824 [update] controller & device info setting page 2021-05-20 03:59:25 +08:00
peterlu14 486fc067ea Merge branch 'fix/replay_mini_no_data' 2021-05-14 00:15:20 +08:00
peterlu14 ad404819b3 Merge branch 'fix/replay_mini_no_data' into feature/aboutPage 2021-05-12 11:46:16 +08:00
TommyXin bed8e72340 clear neulive replay 2021-05-10 20:05:26 +08:00
peterlu14 7ea36c565e [update] about page white list connect 2021-04-28 11:06:20 +08:00
peterlu14 5653c4d3de [update] about content & add new api and factory 2021-04-22 11:32:11 +08:00
peterlu14 227d61d8e4 [update] about page vuex 2021-04-22 11:31:14 +08:00
159 changed files with 8537 additions and 3191 deletions
+18
View File
@@ -14857,6 +14857,11 @@
"is-plain-obj": "^1.0.0"
}
},
"sortablejs": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz",
"integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A=="
},
"source-list-map": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
@@ -15169,6 +15174,11 @@
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
},
"streamsaver": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/streamsaver/-/streamsaver-2.0.5.tgz",
"integrity": "sha512-KIWtBvi8A6FiFZGNSyuIZRZM6C8AvnWTiCx/TYa7so420vC5sQwcBKkdqInuGWoWMfeWy/P+/cRqMtWVf4RW9w=="
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@@ -17248,6 +17258,14 @@
"resolved": "https://registry.npmjs.org/vue-yandex-maps/-/vue-yandex-maps-0.9.0.tgz",
"integrity": "sha512-6gXec68eXNHvo5d6m43lGCDMShYRpciWWy55VA1RiFtMkLHIDeK4CJzYmkfAec32vpzYEqdcNBJh9b93wqtp8w=="
},
"vuedraggable": {
"version": "2.24.3",
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.3.tgz",
"integrity": "sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==",
"requires": {
"sortablejs": "1.10.2"
}
},
"vuestic-ui": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/vuestic-ui/-/vuestic-ui-0.2.2.tgz",
+2
View File
@@ -38,6 +38,7 @@
"popper.js": "^1.16.0",
"regenerator-runtime": "^0.13.3",
"register-service-worker": "^1.6.2",
"streamsaver": "^2.0.5",
"v-tooltip": "^2.0.2",
"vee-validate": "^2.2.13",
"vue": "^2.6.10",
@@ -54,6 +55,7 @@
"vue-router": "^3.1.3",
"vue-worker": "^1.2.1",
"vue-yandex-maps": "^0.9.0",
"vuedraggable": "^2.24.3",
"vuestic-ui": "~0.2.2",
"vuetable-2": "^1.7.5",
"vuex": "^3.1.2",
+2 -1
View File
@@ -49,8 +49,9 @@ Vue.component('chart', ECharts)
Vue.use(VueWorker)
Vue.use(VueAxios, axios)
Vue.use(VueMqtt, 'ws://52.194.17.114:8083')
// Vue.use(VueMqtt, 'ws://52.194.17.114:8083')
// Vue.use(VueMqtt, 'ws://' + location.href.split('/')[2] + ':8083')
Vue.use(VueMqtt, 'ws://' + '192.168.3.48' + ':8083')
Vue.prototype.GLOBAL = global_
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

+35
View File
@@ -0,0 +1,35 @@
<template>
<div class="about">
<controller-info/>
<device-info/>
</div>
</template>
<script>
import DeviceInfo from './deviceInfo.vue'
import ControllerInfo from './controllerInfo.vue'
export default {
name: 'about-content',
components: {
ControllerInfo,
DeviceInfo,
},
created () {
},
data () {
return {
}
},
computed: {
},
watch: {
},
methods: {
},
async mounted () {
},
destroyed () {
},
}
</script>
+141
View File
@@ -0,0 +1,141 @@
<template>
<div class="controller-info">
<div class="row flex">
<div
class="flex sm12 xl12 md12 xs12 ma-2"
v-for="controller in controllers" :key="controller.mac_address"
>
<va-card
style="border: 5px solid #78ceff; border-radius: 30px; font-size: 1.5rem;"
>
<!-- {{ controller }} -->
<va-item :key="controller.device_mac" class="pa-0 ma-0"
>
<va-item-section avatar class="ml-2 mr-2">
<img
:src="getImageUrl()"
:alt="'BPS-CONTROLLER'"
width="300px"
height="300px"
contain
/>
</va-item-section>
<va-item-section class="ml-4" >
<va-item-label style="font-size: 2rem;">
{{ controller.wifi_name }}
</va-item-label>
<va-item-label>
Mac Address :
{{ controller.mac_address.toUpperCase() }}
</va-item-label>
<va-item-label>
Build Version : #
{{ controller.software_version }}
</va-item-label>
<va-item-label>
Update Time :
{{ GLOBAL.dateToStr(controller.updated_at) }}
</va-item-label>
</va-item-section>
</va-item>
</va-card>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters, mapMutations } from 'vuex'
import api from '@/data/api/index'
import types from '@/store/modules/about/types'
import eliteImgUrl from '@/assets/img/elite_img.png'
export default {
name: 'controller-info',
components: {
},
// props: {
// data: {
// type: Object,
// default: function () {
// return {}
// },
// },
// cardclass: {
// type: Array,
// default: function () {
// return ['xs12', 'md12', 'xl12', 'sm12']
// },
// },
// cardheight: {
// type: String,
// default: '82vh',
// },
// cardwidth: {
// type: String,
// default: 'auto',
// },
// },
created () {
},
data () {
return {
}
},
computed: {
controllers () {
return this.getAllController()
},
},
watch: {
},
methods: {
getImageUrl () {
return eliteImgUrl
},
...mapActions('about', [types.controller.init]),
...mapMutations('about', [types.controller.set, types.controller.updateByIndex]),
...mapGetters('about', [types.controller.getAll]),
},
async mounted () {
this.initController({ api: api })
console.log(this.getAllController())
},
destroyed () {
},
}
</script>
<style lang="scss">
.area-style {
height: auto;
overflow-y: hidden;
overflow-x: hidden;
@include media-breakpoint-only(xl) {
height: 48vh;
overflow-y: scroll;
overflow-x: hidden;
}
}
.drag-flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.font-small {
color: rgb(113, 186, 255);
font-size: 16px;
}
.center-medium {
text-align: center;
font-size: 20px;
}
.center-large {
text-align: center;
font-size: 28px;
}
</style>
+166
View File
@@ -0,0 +1,166 @@
<template>
<div class="device-info">
<div class="row flex">
<draggable class="flex d-flex sm12 xl12 md12 xs12" v-model="devices" @start="drag=true" @end="drag=false" >
<div
class="flex d-flex sm12 xl3 md4 xs12 ma-0 area-style "
v-for="(device, index) in devices" :key="device.id"
>
<va-card
:noPadding="true"
style="border: 5px solid #78ceff; border-radius: 30px;"
>
<div class="center-large" >
<div class="flex d-flex sm12 xl12 md12 xs12 ">
<div class="sm11 xl11 md11 xs11 ml-2" style="text-align: start;">
{{ device.name }}
</div>
<div class="sm1 xl1 md1 xs1" style="text-align: right;">
<va-icon
name="ion ion-md-close"
class="mr-1"
color="#babfc2"
style="cursor: pointer;"
@click.native.stop="removeCheck(index, device)"
/>
</div>
</div>
</div>
<div class="center-medium">
<p> {{ device.name }} </p>
</div>
<div class="center-medium">
<p> {{ macArrayToString(device.mac_address) }} </p>
</div>
<div class="mt-4 mb-4" style="text-align: center;">
<img
:src="getImageUrl(device.library)"
:alt="device.name"
width="150px"
height="100px"
contain
/>
</div>
<div class="center-medium">
<p> {{ device.device_version }} </p>
<p> {{ timeStampToLocaleTime(device.updated_at) }} </p>
</div>
<div class="flex sm12 xl12 md12 xs12" style="text-align: center;">
<va-button v-if="device.auto_connect" color="success" @click="autoConnect(index, device)">Auto Connect</va-button>
<va-button v-if="!device.auto_connect" color="#babfc2" @click="autoConnect(index, device)" outline>Auto Connect</va-button>
<va-button >User Guide</va-button>
</div>
</va-card>
</div>
</draggable>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters, mapMutations } from 'vuex'
import api from '@/data/api/index'
import types from '@/store/modules/about/types'
import neuliveImgUrl from '@/assets/img/neulive_img.png'
import eliteImgUrl from '@/assets/img/elite_img.png'
import draggable from 'vuedraggable'
export default {
name: 'device-info',
components: {
draggable,
},
created () {
},
data () {
return {
}
},
computed: {
devices: {
get () {
return this.getAllDevice()
},
set (deviceList) {
this.reorderDevice({ deviceList: deviceList, api: api })
},
},
},
watch: {
},
methods: {
macArrayToString: function (macAddress) {
return this.GLOBAL.transMac(JSON.parse(macAddress))
},
timeStampToLocaleTime: function (time) {
return this.GLOBAL.dateToStr(time)
},
getImageUrl (libraryName) {
if (libraryName !== null) {
if (libraryName.indexOf('Neulive') >= 0) {
return neuliveImgUrl
} else if (libraryName.indexOf('Elite') >= 0) {
return eliteImgUrl
}
}
return null
},
autoConnect (index, device) {
device.auto_connect = !device.auto_connect
this.updateDatabaseByIDDevice({
id: device.id,
request: { auto_connect: device.auto_connect },
api: api,
})
this.updateByIndexDevice({ index: index, item: { auto_connect: device.auto_connect } })
},
removeCheck (index, device) {
/**
* TODO remove modal
*/
this.removeDevice({ id: device.id, index: index, device, deviceList: this.devices, api: api })
},
...mapActions('about', [types.device.init, types.device.remove, types.device.reorder, types.device.updateDatabaseByID]),
...mapMutations('about', [types.device.set, types.device.updateByIndex]),
...mapGetters('about', [types.device.getAll]),
},
async mounted () {
this.initDevice({ api: api })
},
destroyed () {
},
}
</script>
<style lang="scss">
.area-style {
height: auto;
overflow-y: hidden;
overflow-x: hidden;
@include media-breakpoint-only(xl) {
height: 48vh;
overflow-y: scroll;
overflow-x: hidden;
}
}
.drag-flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.font-small {
color: rgb(113, 186, 255);
font-size: 16px;
}
.center-medium {
text-align: center;
font-size: 20px;
}
.center-large {
text-align: center;
font-size: 28px;
}
</style>
+6
View File
@@ -134,3 +134,9 @@ export default {
}
}
</style>
<style lang='scss'>
.layout.gutter--xl {
padding: 0.75rem;
}
</style>
@@ -47,6 +47,13 @@ export const navigationRoutes = {
iconClass: 'vuestic-iconset vuestic-iconset-files',
},
},
{
name: 'settings',
displayName: 'Settings',
meta: {
iconClass: 'vuestic-iconset vuestic-iconset-settings',
},
},
// {
// name: 'forms',
// displayName: 'menu.forms',
File diff suppressed because it is too large Load Diff
@@ -1,15 +1,14 @@
<template>
<div class="flex" :class="cardclass">
<va-card>
<template slot="header">
<!-- <va-icon name="fa fa-area-chart mr-3" color="primary"/> -->
</template>
<va-card :style="'height: ' + cardheight + ';'">
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true"></chart>
</va-card>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import types from '@/store/modules/analysis/replay/types'
// import { chartData } from '../../../../data/task/ChartsManagement'
export default {
@@ -31,7 +30,7 @@ export default {
},
cardheight: {
type: String,
default: '88vh',
default: '82vh',
},
cardwidth: {
type: String,
@@ -57,6 +56,40 @@ export default {
updateZoom: function (e) {
this.$emit('dataZoomEvent', e)
},
mergeOptions (options) {
this.$refs.chart_ref.mergeOptions(options)
},
turnOnAxisEventHandler (eventName, query, handler, attr) {
const chartID = 1
this.updateAxisEventHandlerChart({
chartID: chartID,
axis: attr.axis,
status: 'on',
})
// doc: https://echarts.apache.org/zh/api.html#echartsInstance.on
this.$refs.chart_ref.chart._zr.on(eventName, query, handler)
},
turnOffAxisEventHandler (eventName, handler, attr) {
const chartID = 1
this.updateAxisEventHandlerChart({
chartID: chartID,
axis: attr.axis,
status: 'off',
})
// doc: https://echarts.apache.org/zh/api.html#echartsInstance.off
this.$refs.chart_ref.chart._zr.off(eventName, handler)
},
showLoading (options) {
this.$refs.chart_ref.showLoading(options)
},
hideLoading () {
this.$refs.chart_ref.hideLoading()
},
clear () {
this.$refs.chart_ref.clear()
},
...mapMutations('replay', [types.chart.updateAxisEventHandler]),
},
async mounted () {
this.resizeTimer = setInterval(this.resize, 1000)
@@ -67,3 +100,11 @@ export default {
}
</script>
<style lang='scss'>
.va-card {
&__body {
padding-top: 0.25rem;
}
}
</style>
@@ -0,0 +1,83 @@
<template>
<div class="flex" :class="cardclass">
<va-card :style="'height: 8vh;'">
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true"></chart>
</va-card>
</div>
</template>
<script>
// import { chartData } from '../../../../data/task/ChartsManagement'
export default {
name: 'elite-replay-overview-chart',
components: {
},
props: {
data: {
type: Object,
default: function () {
return {}
},
},
cardclass: {
type: Array,
default: function () {
return ['xs12', 'md12', 'xl12', 'sm12']
},
},
cardheight: {
type: String,
default: '82vh',
},
cardwidth: {
type: String,
default: 'auto',
},
},
created () {
},
data () {
return {
}
},
computed: {
},
watch: {
},
methods: {
resize: function () {
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.resize()
}
},
updateZoom: function (e) {
this.$emit('dataZoomEvent', e)
},
showLoading (options) {
this.$refs.chart_ref.showLoading(options)
},
hideLoading () {
this.$refs.chart_ref.hideLoading()
},
clear () {
this.$refs.chart_ref.clear()
},
},
async mounted () {
this.resizeTimer = setInterval(this.resize, 1000)
},
destroyed () {
clearInterval(this.resizeTimer)
},
}
</script>
<style lang='scss'>
.va-card {
&__body {
padding: 0.75rem;
}
}
</style>
@@ -0,0 +1,105 @@
<template>
<div>
<va-card>
<edit-file-name style="display: inline;" :ref="'edit_file_name'"/>
<download-file style="display: inline;"/>
<delete-file style="display: inline;"/>
<br/>
<change-axis class="box_inline-block" :ref="'change_axis_x'" deviceName="elite" axis="x" @changeAxis="changeAxis" @changeUnit="changeUnit" @clearCycle="clearCycle" @resetScale="resetScale"/>
<change-unit class="box_inline-block" :ref="'change_unit_x'" deviceName="elite" axis="x" @refreshChart="refreshChart"/>
<change-scale class="box_inline-block" :ref="'change_scale_x'" deviceName="elite" axis="x" @refreshChart="refreshChart"/>
<br/>
<change-axis class="box_inline-block" :ref="'change_axis_y'" deviceName="elite" axis="y" @changeAxis="changeAxis" @changeUnit="changeUnit" @clearCycle="clearCycle" @resetScale="resetScale"/>
<change-unit class="box_inline-block" :ref="'change_unit_y'" deviceName="elite" axis="y" @refreshChart="refreshChart"/>
<change-scale class="box_inline-block" :ref="'change_scale_y'" deviceName="elite" axis="y" @refreshChart="refreshChart"/>
<change-cycle style="margin: 3px;" :ref="'change_cycle'" @refreshChart="refreshChart"/>
<show-resample-rate style="margin: 3px;"/>
<show-parameter style="margin: 3px;" :ref="'show_param'" deviceName="elite"/>
</va-card>
</div>
</template>
<script>
import ShowResampleRate from '@/components/analysis/replay/toolbox/ShowResampleRate.vue'
import ChangeAxis from '@/components/analysis/replay/toolbox/ChangeAxis.vue'
import ChangeUnit from '@/components/analysis/replay/toolbox/ChangeUnit.vue'
import ChangeScale from '@/components/analysis/replay/toolbox/ChangeScale.vue'
import ChangeCycle from '@/components/analysis/replay/toolbox/ChangeCycle.vue'
import DownloadFile from '@/components/analysis/replay/toolbox/DownloadFile.vue'
import DeleteFile from '@/components/analysis/replay/toolbox/DeleteFile.vue'
import EditFileName from '@/components/analysis/replay/toolbox/EditFileName.vue'
import ShowParameter from '@/components/analysis/replay/toolbox/ShowParameter.vue'
export default {
name: 'top-control-panel',
components: {
ShowResampleRate,
ChangeAxis,
ChangeUnit,
ChangeScale,
ChangeCycle,
DownloadFile,
DeleteFile,
EditFileName,
ShowParameter,
},
computed: {
},
props: {
},
async created () {
},
data () {
return {
}
},
mqtt: {
},
methods: {
init () {
this.$refs.change_axis_x.init()
this.$refs.change_axis_y.init()
this.$refs.change_unit_x.init()
this.$refs.change_unit_y.init()
this.$refs.change_scale_x.init()
this.$refs.change_scale_y.init()
this.$refs.change_cycle.init()
this.$refs.edit_file_name.init()
this.$refs.show_param.init()
},
refreshChart (options) {
this.$emit('refreshChart', options)
},
changeAxis (gridIndex) {
this.$emit('changeAxis', gridIndex)
},
changeUnit (axis) {
if (axis === 'x') {
this.$refs.change_unit_x.changeUnitByAxis()
} else if (axis === 'y') {
this.$refs.change_unit_y.changeUnitByAxis()
}
},
clearCycle () {
this.$refs.change_cycle.clear()
},
resetScale () {
this.$refs.change_scale_x.reset()
this.$refs.change_scale_y.reset()
},
},
// use watch because va-select with @change will have bug
watch: {
},
mounted () {
},
}
</script>
<style lang="scss">
.box_inline-block {
padding: 2px;
margin: 2px;
display: inline-block;
}
</style>
File diff suppressed because it is too large Load Diff
@@ -7,6 +7,8 @@
</template>
<script>
import { mapMutations } from 'vuex'
import types from '@/store/modules/analysis/replay/types'
// import { chartData } from '../../../../data/task/ChartsManagement'
export default {
@@ -54,6 +56,40 @@ export default {
updateZoom: function (e) {
this.$emit('dataZoomEvent', e)
},
mergeOptions (options) {
this.$refs.chart_ref.mergeOptions(options)
},
turnOnAxisEventHandler (eventName, query, handler, attr) {
const chartID = 1
this.updateAxisEventHandlerChart({
chartID: chartID,
axis: attr.axis,
status: 'on',
})
// doc: https://echarts.apache.org/zh/api.html#echartsInstance.on
this.$refs.chart_ref.chart._zr.on(eventName, query, handler)
},
turnOffAxisEventHandler (eventName, handler, attr) {
const chartID = 1
this.updateAxisEventHandlerChart({
chartID: chartID,
axis: attr.axis,
status: 'off',
})
// doc: https://echarts.apache.org/zh/api.html#echartsInstance.off
this.$refs.chart_ref.chart._zr.off(eventName, handler)
},
showLoading (options) {
this.$refs.chart_ref.showLoading(options)
},
hideLoading () {
this.$refs.chart_ref.hideLoading()
},
clear () {
this.$refs.chart_ref.clear()
},
...mapMutations('replay', [types.chart.updateAxisEventHandler]),
},
async mounted () {
this.resizeTimer = setInterval(this.resize, 1000)
@@ -0,0 +1,83 @@
<template>
<div class="flex" :class="cardclass">
<va-card :style="'height: 8vh;'">
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true"></chart>
</va-card>
</div>
</template>
<script>
// import { chartData } from '../../../../data/task/ChartsManagement'
export default {
name: 'neulive-replay-overview-chart',
components: {
},
props: {
data: {
type: Object,
default: function () {
return {}
},
},
cardclass: {
type: Array,
default: function () {
return ['xs12', 'md12', 'xl12', 'sm12']
},
},
cardheight: {
type: String,
default: '82vh',
},
cardwidth: {
type: String,
default: 'auto',
},
},
created () {
},
data () {
return {
}
},
computed: {
},
watch: {
},
methods: {
resize: function () {
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.resize()
}
},
updateZoom: function (e) {
this.$emit('dataZoomEvent', e)
},
showLoading (options) {
this.$refs.chart_ref.showLoading(options)
},
hideLoading () {
this.$refs.chart_ref.hideLoading()
},
clear () {
this.$refs.chart_ref.clear()
},
},
async mounted () {
this.resizeTimer = setInterval(this.resize, 1000)
},
destroyed () {
clearInterval(this.resizeTimer)
},
}
</script>
<style lang='scss'>
.va-card {
&__body {
padding: 0.75rem;
}
}
</style>
@@ -0,0 +1,70 @@
<template>
<div>
<va-card>
<edit-file-name style="display: inline;" :ref="'edit_file_name'"/>
<download-file style="display: inline;"/>
<delete-file style="display: inline;"/>
<show-resample-rate/>
<change-unit v-show="showXUnit" :ref="'change_unit_x'" deviceName="neulive" axis="x" @refreshChart="refreshChart"/>
<change-unit :ref="'change_unit_y'" deviceName="neulive" axis="y" @refreshChart="refreshChart"/>
<change-scale :ref="'change_scale_y'" deviceName="neulive" axis="y" @refreshChart="refreshChart"/>
<show-parameter :ref="'show_param'" deviceName="neulive"/>
</va-card>
</div>
</template>
<script>
import ShowResampleRate from '@/components/analysis/replay/toolbox/ShowResampleRate.vue'
import ChangeUnit from '@/components/analysis/replay/toolbox/ChangeUnit.vue'
import ChangeScale from '@/components/analysis/replay/toolbox/ChangeScale.vue'
import DownloadFile from '@/components/analysis/replay/toolbox/DownloadFile.vue'
import DeleteFile from '@/components/analysis/replay/toolbox/DeleteFile.vue'
import EditFileName from '@/components/analysis/replay/toolbox/EditFileName.vue'
import ShowParameter from '@/components/analysis/replay/toolbox/ShowParameter.vue'
export default {
name: 'top-control-panel',
components: {
ShowResampleRate,
ChangeUnit,
ChangeScale,
DownloadFile,
DeleteFile,
EditFileName,
ShowParameter,
},
computed: {
},
props: {
},
async created () {
},
data () {
return {
showXUnit: false,
}
},
mqtt: {
},
methods: {
init () {
this.$refs.change_unit_x.init()
this.$refs.change_unit_y.init()
this.$refs.change_scale_y.init()
this.$refs.edit_file_name.init()
this.$refs.show_param.init()
},
refreshChart (options) {
this.$emit('refreshChart', options)
},
},
// use watch because va-select with @change will have bug
watch: {
},
mounted () {
},
}
</script>
<style lang="scss">
</style>
@@ -0,0 +1,166 @@
<template>
<div>
<span> {{ axis }} axis: </span>
<div v-if="axis === 'x'" style="display: inline;">
<select v-model="channelFormat" @change="changeAxis()">
<option v-for="option in channelOptions" :key="option.id" :value="option">
{{ option.description }}
</option>
</select>
</div>
<div v-if="axis === 'y'" style="display: inline;">
<select v-model="channelFormat" @change="changeAxis()">
<option v-for="option in channelYOptions" :key="option.id" :value="option">
{{ option.description }}
</option>
</select>
</div>
</div>
</template>
<script>
import { mapFields } from 'vuex-map-fields'
import { newChartMode } from '@/factories/chart/chartFactory'
export default {
name: 'change-axis',
components: {
},
props: {
deviceName: {
type: String, // elite or neulive
},
axis: {
type: String, // x or y
},
metaIndex: {
type: Number, // which meta file
default: 0,
},
},
created () {
},
computed: {
...mapFields('replay', [
'chartData',
'metaList',
'axisXDataType',
'axisYDataType',
]),
},
methods: {
init () {
if (this.deviceName === 'neulive') {
// now neulive only v-t
if (this.axis === 'x') {
this.axisXDataType = this.channelOptions[3]
} else if (this.axis === 'y') {
this.axisYDataType = this.channelOptions[1]
}
} else if (this.deviceName === 'elite') {
// use state meta to decide which default unit need to be used (like check I-V mode...)
const setting = newChartMode(this.metaList[this.metaIndex].parameter_set.MODE)
const xType = setting[0]
const xValue = setting[1]
const yType = setting[2]
const yValue = setting[3]
let settingType
let settingValue
if (this.axis === 'x') {
settingType = xType
settingValue = xValue
if (settingType === 'Elite') {
// 1: I, 2: V, 3: R
if (settingValue === 1) {
this.axisXDataType = this.channelOptions[0]
} else if (settingValue === 2) {
this.axisXDataType = this.channelOptions[1]
} else if (settingValue === 3) {
this.axisXDataType = this.channelOptions[2]
}
} else if (settingType === 'Time') {
this.axisXDataType = this.channelOptions[3]
}
this.channelFormat = this.axisXDataType
} else if (this.axis === 'y') {
settingType = yType
settingValue = yValue
if (settingType === 'Elite') {
// 1: I, 2: V, 3: R
if (settingValue === 1) {
this.axisYDataType = this.channelOptions[0]
} else if (settingValue === 2) {
this.axisYDataType = this.channelOptions[1]
} else if (settingValue === 3) {
this.axisYDataType = this.channelOptions[2]
}
} else if (settingType === 'Time') {
this.axisYDataType = this.channelOptions[3]
}
this.channelFormat = this.axisYDataType
}
}
if (this.axis === 'y') { // only need to draw once time when init
this.changeAxis()
}
},
changeAxis () {
if (this.axis === 'x') {
this.axisXDataType = this.channelFormat
} else if (this.axis === 'y') {
this.axisYDataType = this.channelFormat
}
if (this.deviceName === 'neulive') {
console.log('(Last updated: 2021/06/07) [TODO] for elite now, cuz neulive now only have v-t graph, for future neulive replay need to adjust')
} else if (this.deviceName === 'elite') {
this.$emit('changeAxis', this.metaIndex) // temporarily use metaIndex for gridIndex
this.$emit('changeUnit', this.axis)
this.$emit('resetScale')
this.$emit('clearCycle')
}
},
},
mounted () {
},
data () {
return {
channelFormat: {},
channelOptions: [
{
id: 0,
description: 'Current',
},
{
id: 1,
description: 'Voltage',
},
{
id: 2,
description: 'Resistance',
},
{
id: 100, // no usage, so assign a large number to avoid conflicting with existing channel data
description: 'Time',
},
],
channelYOptions: [
{
id: 0,
description: 'Current',
},
{
id: 1,
description: 'Voltage',
},
{
id: 2,
description: 'Resistance',
},
],
}
},
destroyed () {
},
}
</script>
@@ -0,0 +1,99 @@
<template>
<div>
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal.minMaxPanel"
size="small"
:position="position"
:title="'Set min max (if blank, will be auto-set)'"
:okText=" $t('modal.confirm') "
@ok="setMinMax()"
>
<va-input
v-model="minMaxInfo[gridIndex].max"
:label="'Max'"
/>
<va-input
v-model="minMaxInfo[gridIndex].min"
:label="'Min'"
/>
</va-modal>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { mapFields } from 'vuex-map-fields'
import types from '@/store/modules/analysis/replay/types'
export default {
name: 'change-channel-value-min-max',
components: {
},
props: {
chartID: {
type: Number,
default: 1, // detail data
},
},
created () {
},
data () {
return {
gridIndex: 0,
axis: 'y',
showModal: {
minMaxPanel: false,
},
minMaxInfo: { 0: { min: '', max: '' } }, // will be set by init()
position: 'center',
}
},
computed: {
...mapFields('replay', [
'chartData',
]),
},
watch: {
},
methods: {
init () {
const len = this.chartData[this.chartID].series.length
for (let i = 0; i < len; i++) {
this.minMaxInfo[i] = { min: '', max: '' }
}
},
showPanel (params) {
if (params.target !== undefined) {
if (params.target.eventData.componentType === 'xAxis' && params.target.eventData.targetType === 'axisLabel') {
this.gridIndex = params.target.eventData.xAxisIndex
this.axis = 'x'
this.position = 'bottom'
} else if (params.target.eventData.componentType === 'yAxis' && params.target.eventData.targetType === 'axisLabel') {
this.gridIndex = params.target.eventData.yAxisIndex
this.axis = 'y'
this.position = 'left'
}
this.showModal.minMaxPanel = true
}
},
setMinMax () {
this.updateAxisValMinMaxChart({
chartID: this.chartID,
axis: this.axis,
axisIndex: this.gridIndex,
minVal: this.minMaxInfo[this.gridIndex].min,
maxVal: this.minMaxInfo[this.gridIndex].max,
})
this.$emit('refreshChart', this.chartData[this.chartID])
},
...mapMutations('replay', [types.chart.updateAxisValMinMax]),
},
mounted () {
},
destroyed () {
},
}
</script>
@@ -0,0 +1,153 @@
<template>
<div v-show="showPanel">
<va-input
v-model="showWhichCycles"
@change="setCycle"
:label="$t('See which cycles')"
/>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { mapFields } from 'vuex-map-fields'
import types from '@/store/modules/analysis/replay/types'
export default {
name: 'change-cycle',
components: {
},
props: {
chartID: {
type: Number,
default: 1, // detail data
},
metaIndex: {
type: Number, // which meta file
default: 0,
},
},
created () {
},
data () {
return {
showPanel: true,
metaID: 0,
showWhichCycles: '',
cycleNum: 0,
cycleDataID: 3, // [TODO] manage by data type factory
}
},
computed: {
slices: function () {
const cycleList = this.showWhichCycles.split(',')
if (cycleList.length === 1 && cycleList[0] === '') {
return ''
}
for (let i = 0; i < cycleList.length; i++) {
const element = cycleList[i]
if (element.includes('-')) {
const startIndex = element.split('-')[0]
const endIndex = element.split('-')[1]
cycleList[i] = startIndex
for (let j = endIndex; j >= parseInt(startIndex) + 1; j--) {
cycleList.splice(i + 1, 0, j.toString()) // arr.splice(index, 0, item); will insert item into arr at the specified index (deleting 0 items first, that is, it's just an insert).
}
}
}
// console.log(cycleList)
return cycleList
},
...mapFields('replay', [
'chartData',
'recInfo',
'metaList',
'currentScale',
'axisXDataType',
'axisYDataType',
]),
},
watch: {
},
methods: {
init () {
this.cycleNum = this.metaList[this.metaIndex].parameter_set.CYCLE_NUMBER
this.metaID = this.metaList[this.metaIndex].id
if (this.cycleNum === 0) {
this.showPanel = false
}
},
clear () {
this.showWhichCycles = ''
},
setCycle () {
console.log('setCycle')
if (this.cycleNum !== 0) {
// get cycle data
const allCycleData = this.recInfo[this.metaID][this.cycleDataID][this.currentScale][this.metaIndex].data
var cycleDict = {}
var cycleStartIndex = 0
var cycleEndIndex = 0
var currentCycleIndex = 0
for (let index = 0; index < allCycleData.length; index++) {
const value = allCycleData[index]
const cycleIndex = parseInt(value[1])
if (cycleIndex === currentCycleIndex) {
if (currentCycleIndex in cycleDict) {
cycleEndIndex = index
cycleDict[cycleIndex][1] = cycleEndIndex
} else {
cycleDict[cycleIndex] = [cycleStartIndex, cycleEndIndex]
}
} else {
cycleStartIndex = index
currentCycleIndex++
}
}
// get recording data
let allXData
if (this.axisXDataType.description !== 'Time') {
allXData = this.recInfo[this.metaID][this.axisXDataType.id][this.currentScale][this.metaIndex].data
}
const allYData = this.recInfo[this.metaID][this.axisYDataType.id][this.currentScale][this.metaIndex].data
const data = []
for (let sliceIndex = 0; sliceIndex < this.cycleNum; sliceIndex++) {
// console.log(this.slices)
if (this.slices === '' || this.slices.includes((sliceIndex + 1).toString())) {
// slice data
const value = cycleDict[sliceIndex + 1]
const start = value[0]
const end = value[1] + 1
const sliceYData = allYData.slice(start, end)
const sliceLen = sliceYData.length
if (allXData !== undefined) {
const sliceXData = allXData.slice(start, end)
for (let j = 0; j < sliceLen; j++) {
data.push([sliceXData[j][1], sliceYData[j][1]])
}
} else {
const sliceYData = allYData.slice(start, end)
for (let j = 0; j < sliceLen; j++) {
data.push(sliceYData[j])
}
}
}
}
this.updateSeriesChart({
chartID: this.chartID,
seriesIndex: this.metaIndex,
data: JSON.parse(JSON.stringify(data)),
})
}
this.$emit('refreshChart', this.chartData[this.chartID])
},
...mapMutations('replay', [types.chart.updateSeries]),
},
mounted () {
},
destroyed () {
},
}
</script>
@@ -0,0 +1,149 @@
<template>
<div>
<select v-model="scaleFormat" @change="changeScale()">
<option v-for="option in scaleOptions" :key="option.id" :value="option">
{{ option.description }}
</option>
</select>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { mapFields } from 'vuex-map-fields'
import types from '@/store/modules/analysis/replay/types'
export default {
name: 'change-scale',
components: {
},
props: {
deviceName: {
type: String, // elite or neulive
},
chartID: {
type: Number, // detail data
default: 1,
},
axis: {
type: String, // x or y
},
metaIndex: {
type: Number, // which meta file
default: 0,
},
},
created () {
},
computed: {
...mapFields('replay', [
'chartData',
'recInfo',
'metaList',
'axisXLabelScale',
'axisYLabelScale',
'axisXDataType',
'axisYDataType',
'startTimeCurrent',
'endTimeCurrent',
'currentScale',
]),
},
methods: {
init () {
this.metaID = this.metaList[this.metaIndex].id
if (this.axis === 'x') {
this.axisXLabelScale = this.scaleOptions[0] // 0 mean use default unit
this.scaleFormat = this.axisXLabelScale
} else if (this.axis === 'y') {
this.axisYLabelScale = this.scaleOptions[0] // 0 mean use default unit
this.scaleFormat = this.axisYLabelScale
}
},
changeScale () {
if (this.axis === 'x') {
this.axisXLabelScale = this.scaleFormat
} else if (this.axis === 'y') {
this.axisYLabelScale = this.scaleFormat
}
if (this.deviceName === 'neulive') {
const keys = Object.keys(this.metaList[this.metaIndex].mini_data)
for (let gridIndex = 0; gridIndex < keys.length; gridIndex++) {
const key = keys[gridIndex]
if (parseInt(key) < 255) { // 256: x, 257: y, 258: z, 259: mag
this.calculateScaleHelper(gridIndex)
}
}
} else if (this.deviceName === 'elite') {
this.calculateScaleHelper(this.metaIndex)
}
this.$emit('refreshChart', this.chartData[this.chartID])
},
calculateScaleHelper (gridIndex) {
let seriesData
if (this.scaleFormat.description === 'Log') {
seriesData = JSON.parse(JSON.stringify(this.chartData[this.chartID].series[gridIndex].data))
for (let i = 0; i < seriesData.length; i++) {
if (this.axis === 'x') {
seriesData[i][0] = Math.log10(Math.abs(seriesData[i][0]))
} else if (this.axis === 'y') {
seriesData[i][1] = Math.log10(Math.abs(seriesData[i][1]))
}
}
} else if (this.scaleFormat.description === 'Linear') {
let allXData
if (this.axisXDataType.description !== 'Time') {
allXData = this.recInfo[this.metaID][this.axisXDataType.id][this.currentScale][gridIndex].data
}
const allYData = this.recInfo[this.metaID][this.axisYDataType.id][this.currentScale][gridIndex].data
seriesData = []
for (let i = 0, len = allYData.length; i < len; i++) {
if (parseInt(allYData[i][0]) >= this.startTimeCurrent && parseInt(allYData[i][0]) <= this.endTimeCurrent) {
const processedData = JSON.parse(JSON.stringify(allYData[i]))
if (allXData !== undefined) {
processedData[0] = allXData[i][1]
}
seriesData.push(processedData)
}
}
}
this.updateSeriesChart({
chartID: this.chartID,
seriesIndex: gridIndex,
data: JSON.parse(JSON.stringify(seriesData)),
})
},
reset () {
if (this.axis === 'x') {
this.axisXLabelScale = this.scaleOptions[0] // 0 mean use default unit
this.scaleFormat = this.axisXLabelScale
} else if (this.axis === 'y') {
this.axisYLabelScale = this.scaleOptions[0] // 0 mean use default unit
this.scaleFormat = this.axisYLabelScale
}
},
...mapMutations('replay', [types.chart.updateSeries]),
},
mounted () {
},
data () {
return {
metaID: 0,
scaleFormat: { id: 0, description: 'Linear' },
scaleOptions: [
{
id: 0,
description: 'Linear',
},
{
id: 1,
description: 'Log',
},
],
}
},
destroyed () {
},
}
</script>
@@ -0,0 +1,224 @@
<template>
<div>
<select v-model="valueFormat" @change="changeUnit()">
<option v-for="option in valueFormatOptions[dataType]" :key="option.id" :value="option">
{{ option.unit }}
</option>
</select>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { mapFields } from 'vuex-map-fields'
import types from '@/store/modules/analysis/replay/types'
import { newChartMode } from '@/factories/chart/chartFactory'
export default {
name: 'change-unit',
components: {
},
props: {
deviceName: {
type: String, // elite or neulive
},
axis: {
type: String, // x or y
},
metaIndex: {
type: Number, // which meta file
default: 0,
},
},
created () {
},
computed: {
...mapFields('replay', [
'chartData',
'metaList',
'valueFormatX',
'valueFormatY',
'axisXDataType',
'axisYDataType',
]),
},
methods: {
init () {
if (this.deviceName === 'neulive') {
// now neulive only v-t
if (this.axis === 'x') {
this.dataType = 'time'
} else if (this.axis === 'y') {
this.dataType = 'voltage'
}
} else if (this.deviceName === 'elite') {
// use state meta to decide which default unit need to be used (like check I-V mode...)
const setting = newChartMode(this.metaList[this.metaIndex].parameter_set.MODE)
const xType = setting[0]
const xValue = setting[1]
const yType = setting[2]
const yValue = setting[3]
let settingType
let settingValue
if (this.axis === 'x') {
settingType = xType
settingValue = xValue
} else if (this.axis === 'y') {
settingType = yType
settingValue = yValue
}
if (settingType === 'Elite') {
// 1: I, 2: V, 3: R
if (settingValue === 1) {
this.dataType = 'current'
} else if (settingValue === 2) {
this.dataType = 'voltage'
} else if (settingValue === 3) {
this.dataType = 'resistance'
}
} else if (settingType === 'Time') {
this.dataType = 'time'
}
}
if (this.axis === 'x') {
this.valueFormatX = this.valueFormatOptions[this.dataType][0]
this.valueFormat = this.valueFormatX
} else if (this.axis === 'y') {
this.valueFormatY = this.valueFormatOptions[this.dataType][0] // 0 mean use default unit (i.e. unitScale = 1)
this.valueFormat = this.valueFormatY
}
this.changeUnit()
},
changeUnit () {
if (this.axis === 'x') {
this.valueFormatX = this.valueFormat
} else if (this.axis === 'y') {
this.valueFormatY = this.valueFormat
}
const chartID = 1 // detail data
if (this.deviceName === 'neulive') {
const keys = Object.keys(this.metaList[this.metaIndex].mini_data)
for (let axisIndex = 0; axisIndex < keys.length; axisIndex++) {
const key = keys[axisIndex]
if (parseInt(key) < 255) { // 256: x, 257: y, 258: z, 259: mag
this.updateAxisLabelChart({
chartID: chartID,
axis: this.axis,
axisIndex: axisIndex,
})
}
}
} else if (this.deviceName === 'elite') {
this.updateAxisLabelChart({
chartID: chartID,
axis: this.axis,
axisIndex: this.metaIndex,
})
}
this.$emit('refreshChart', this.chartData[chartID])
},
changeUnitByAxis () {
if (this.axis === 'x') {
if (this.axisXDataType.description === 'Current') {
this.dataType = 'current'
} else if (this.axisXDataType.description === 'Voltage') {
this.dataType = 'voltage'
} else if (this.axisXDataType.description === 'Resistance') {
this.dataType = 'resistance'
} else if (this.axisXDataType.description === 'Time') {
this.dataType = 'time'
}
} else if (this.axis === 'y') {
if (this.axisYDataType.description === 'Current') {
this.dataType = 'current'
} else if (this.axisYDataType.description === 'Voltage') {
this.dataType = 'voltage'
} else if (this.axisYDataType.description === 'Resistance') {
this.dataType = 'resistance'
}
}
this.valueFormat = this.valueFormatOptions[this.dataType][0]
this.changeUnit()
},
// call vuex to mutate chart label formatter by unit and axis
...mapMutations('replay', [types.chart.updateAxisLabel]),
},
mounted () {
},
data () {
return {
dataType: '',
valueFormat: {},
valueFormatOptions: { // below id: 0 mean default
current: [
{
id: 0,
unit: 'nA',
unitScale: 1,
},
{
id: 1,
unit: 'uA',
unitScale: 1000,
},
{
id: 2,
unit: 'mA',
unitScale: 1000000,
},
],
voltage: [ // Voltage
{
id: 0,
unit: 'uV',
unitScale: 1,
},
{
id: 1,
unit: 'mV',
unitScale: 1000,
},
{
id: 2,
unit: 'V',
unitScale: 1000000,
},
],
resistance: [ // Resistance
{
id: 0,
unit: 'mΩ',
unitScale: 1,
},
{
id: 1,
unit: 'Ω',
unitScale: 1000,
},
{
id: 2,
unit: 'kΩ',
unitScale: 1000000,
},
{
id: 3,
unit: 'MΩ',
unitScale: 1000000000,
},
],
time: [ // Time
{
id: 0,
unit: 'auto',
unitScale: 1,
},
],
},
}
},
destroyed () {
},
}
</script>
@@ -0,0 +1,116 @@
<template>
<div>
<va-button flat small class="resize-va-button" color="gray" icon="fa fa-trash" @click.stop="deleteFileConfirm()"/>
<va-modal
v-model="showModal.deleteFile"
size="small"
:title="'DELETE'"
:message="`Delete File?`"
:okText=" $t('modal.confirm') "
@ok="deleteFile()"
>
</va-modal>
</div>
</template>
<script>
import api from '@/data/api/index'
import { mapFields } from 'vuex-map-fields'
export default {
name: 'delete-file',
components: {
},
props: {
},
created () {
},
data () {
return {
showModal: {
deleteFile: false,
},
deleteInfoList: [],
deleteInfoTemplate: {
path: '',
name: '',
metaID: 0, // id will be set later
rawChannelAndIDArrays: [], // list of lists
miniChannelAndIDArrays: [], // list of lists
},
}
},
computed: {
...mapFields('replay', [
'metaList',
]),
},
watch: {
},
methods: {
deleteFileConfirm: function () {
for (let i = 0; i < this.metaList.length; i++) {
const info = this.metaList[i]
this.deleteInfoTemplate.path = info.path
this.deleteInfoTemplate.name = info.name
this.deleteInfoTemplate.metaID = info.id
this.deleteInfoTemplate.rawChannelAndIDArrays = [] // list of lists
this.deleteInfoTemplate.miniChannelAndIDArrays = [] // list of lists
for (const [channel, idArray] of Object.entries(info.raw_data)) {
this.deleteInfoTemplate.rawChannelAndIDArrays.push([channel, idArray[0]])
}
for (const [channel, scaleObject] of Object.entries(info.mini_data)) {
for (const idArray of Object.values(scaleObject)) {
this.deleteInfoTemplate.miniChannelAndIDArrays.push([channel, idArray[0]])
}
}
this.deleteInfoList.push(JSON.parse(JSON.stringify(this.deleteInfoTemplate))) // deep copy data
}
this.showModal.deleteFile = true
},
deleteFile: async function () {
for (let i = 0; i < this.deleteInfoList.length; i++) {
const deleteInfo = this.deleteInfoList[i]
for (const item of deleteInfo.rawChannelAndIDArrays) {
const channel = item[0]
const id = item[1]
await api.raw.update(channel, id, { deleted: true })
await api.raw.clearDel(channel, id)
}
for (const item of deleteInfo.miniChannelAndIDArrays) {
const channel = item[0]
const id = item[1]
await api.mini.update(channel, id, { deleted: true })
await api.mini.clearDel(channel, id)
}
await api.meta.update(deleteInfo.metaID, { deleted: true })
await api.meta.clearDel(deleteInfo.metaID)
}
await this.deleteFileDone()
},
deleteFileDone: async function () {
this.showToast('Deleted success', {
position: 'bottom-right',
})
this.$router.go(-1)
},
},
mounted () {
},
destroyed () {
},
}
</script>
<style lang="scss">
.resize-va-button {
.va-button {
margin: 0.375rem 0.5rem 0.375rem 0.1px;
}
.va-button--small {
padding: 0.1px;
}
}
</style>
@@ -0,0 +1,57 @@
<template>
<div>
<va-button flat small class="resize-va-button" color="gray" icon="fa fa-download" @click.stop="downloadCSV()"/>
</div>
</template>
<script>
// import { download } from '@/data/download/Download'
// import { exportData } from '@/data/export/export'
import { mapFields } from 'vuex-map-fields'
export default {
name: 'download-file',
components: {
},
props: {
},
created () {
},
data () {
return {
}
},
computed: {
...mapFields('replay', [
'metaList',
]),
},
watch: {
},
methods: {
downloadCSV: async function () {
for (let i = 0; i < this.metaList.length; i++) {
const meta = this.metaList[i]
window.open('http://' + location.href.split('/')[2].split(':')[0] + '/#/admin/download/neulive/csv/' + meta.id, '_blank', 'width=500,height=100,left=200,top=200')
}
},
},
mounted () {
},
destroyed () {
},
}
</script>
<style lang="scss">
.resize-va-button {
.va-button {
margin: 0.375rem 0.5rem 0.375rem 0.1px;
}
.va-button--small {
padding: 0.1px;
}
}
</style>
@@ -0,0 +1,153 @@
<template>
<div>
<va-button flat small class="resize-va-button" color="gray" icon="fa fa-file-text-o" @click.stop="editFileConfirm()"> {{ filename }} </va-button>
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal.editFile"
size="small"
:title="'CHANGE FILE NAME'"
:okText=" $t('modal.confirm') "
@ok="editFile()"
@cancel="undoEdit()"
>
<va-input
:value="editInfo.changedName"
:label="'Name'"
:placeholder="editInfo.name"
:success="editInfo.success"
:error="editInfo.error"
:error-messages="editInfo.errorMessages"
@input="checkFileNameValidate"
removable
/>
</va-modal>
</div>
</template>
<script>
import api from '@/data/api/index'
import { debounce } from 'lodash'
import { file } from '@/data/file/File'
import { mapFields } from 'vuex-map-fields'
export default {
name: 'edit-file-name',
components: {
},
props: {
},
created () {
},
data () {
return {
fileLists: [],
showModal: {
editFile: false,
},
editInfo: {
info: { id: 0 }, // id will be set in init()
changedName: '',
success: false,
error: false,
errorMessagesAll: ['File name contains illegal character', 'File name empty', 'File name exist'],
errorMessages: [],
},
filename: '',
}
},
computed: {
...mapFields('replay', [
'metaList',
]),
},
watch: {
},
methods: {
init () {
// [TODO] 0: not sure future UX design
const meta = this.metaList[0]
this.updateFileLists()
this.filename = meta.name
this.editInfo.changedName = meta.name
this.editInfo.info.id = meta.id
},
editFileConfirm () {
this.updateFileLists()
this.showModal.editFile = true
},
async updateFileLists () {
this.fileLists = []
// [TODO] 0: not sure future UX design
const meta = this.metaList[0]
file.clearFileList()
const files = await api.meta.getCollectionByParent('folder', meta.parent.folder[0])
file.updateFileList(files)
const tmpFiles = file.getFileList()
for (let i = 0; i < tmpFiles.length; i++) {
const tmp = tmpFiles[i]
this.fileLists.push(tmp)
}
},
editFile: async function () {
if (this.editInfo.success === true) {
await api.meta.update(this.editInfo.info.id, { name: this.editInfo.changedName })
this.editInfo.name = this.editInfo.changedName
this.filename = this.editInfo.changedName
}
},
undoEdit: function () {
this.editInfo.success = false
this.editInfo.error = false
this.editInfo.changedName = this.filename
this.editInfo.name = ''
this.editInfo.path = ''
},
checkFileNameValidate: debounce(function (term) {
const illegalChar = term.match(/[^(\w\-)]+/gm)
if (term.length === 0) {
// input text empty
this.editInfo.error = true
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[1])
} else if (illegalChar !== null) {
// input text illegal
this.editInfo.error = true
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[0] + ' ' + illegalChar[0])
} else {
const existedFile = this.fileLists.filter(file => file.name.replace('/', '') === term)
if (existedFile.length === 0) {
this.editInfo.error = false
this.editInfo.success = true
} else {
// file name exist
this.editInfo.error = true
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[2])
}
}
this.editInfo.changedName = term
}, 200),
},
mounted () {
},
destroyed () {
},
}
</script>
<style lang="scss">
.resize-va-button {
.va-button {
margin: 0.375rem 0.5rem 0.375rem 0.1px;
}
.va-button--small {
padding: 0.1px;
}
}
</style>
@@ -0,0 +1,516 @@
<template>
<va-tree-root>
<va-tree-category label="Experiment Setting" :isOpen="false">
<pre><div style="text-transform: none;" class="title mb-3" :style="{color: this.$themes.primary}" v-html="content"></div></pre>
</va-tree-category>
</va-tree-root>
</template>
<script>
import { mapFields } from 'vuex-map-fields'
export default {
name: 'show-parameter',
components: {
},
props: {
deviceName: {
type: String, // elite or neulive
},
metaIndex: {
type: Number, // which meta file
default: 0,
},
},
created () {
},
data () {
return {
content: '',
// [region] for neulive
ampGainOptions: [
{
id: 0,
description: '25',
},
{
id: 1,
description: '100',
},
{
id: 2,
description: '400',
},
{
id: 3,
description: '800',
},
],
neuliveSampleRateOptions: [
{
id: 0,
value: 800,
description: '1k',
},
{
id: 1,
value: 400,
description: '2k',
},
{
id: 2,
value: 200,
description: '4k',
},
{
id: 3,
value: 160,
description: '5k',
},
{
id: 4,
value: 100,
description: '8k',
},
{
id: 5,
value: 80,
description: '10k',
},
],
stimulateElectrodeOptions: [
{
label: 'Monopolar',
value: 0,
},
{
label: 'Bipolar',
value: 1,
},
],
cycleNumberOptions: [
{
label: 'limite',
value: 0,
},
{
label: 'Unlimite',
value: 1,
},
],
patternModeOptions: [
{
label: 'Monophasic',
value: 0,
},
{
label: 'Biphasic',
value: 1,
},
],
unitOptions: [
{
label: 's',
value: 0,
},
{
label: 'ms',
value: 1,
},
{
label: 'us',
value: 2,
},
],
// [Endregion]
// [region] for elite
workingModeOptions: [
{
id: 0,
description: 'I-V Curve',
},
{
id: 1,
description: 'Cycle I-V',
},
{
id: 2,
description: 'Function Generator',
},
{
id: 3,
description: 'R-T Graph',
},
{
id: 4,
description: 'V-T Graph',
},
{
id: 5,
description: 'I-T Graph',
},
{
id: 6,
description: 'ADC_Test',
},
{
id: 7,
description: 'Constant Current',
},
{
id: 8,
description: 'Cyclic Voltammetry',
},
{
id: 9,
description: 'Cyclic Voltammetry-hi-cycles',
},
{
id: 10,
description: 'Linear Sweep Voltammetry',
},
{
id: 11,
description: 'Chronoamperometric Graph',
},
],
currentRangeOptions: [
{
value: 0,
label: '<40 μA',
},
{
value: 1,
label: '30-1350 μA',
},
{
value: 2,
label: '>1000 μA',
},
{
value: 3,
label: 'Auto',
},
],
stepTimeOptions: [
{
value: 0,
label: '0.5s',
},
{
value: 1,
label: '1.0s',
},
{
value: 2,
label: '2.0s',
},
],
resisterRangeOptions: [
{
value: 0,
label: '>50 kΩ',
},
{
value: 1,
label: '2-100 kΩ',
},
{
value: 2,
label: '<10 kΩ',
},
{
value: 3,
label: 'Auto',
},
],
eliteSampleRateOptions: [
{
value: 0,
label: '100',
},
{
value: 1,
label: '10',
},
{
value: 2,
label: '5',
},
{
value: 3,
label: '1',
},
{
value: 4,
label: '0.1',
},
{
value: 5,
label: '0.01',
},
],
chargeOptions: [
{
value: 0,
label: 'Charge',
},
{
value: 1,
label: 'Discharge',
},
],
// [Endregion]
}
},
computed: {
...mapFields('replay', [
'metaList',
]),
},
watch: {
},
methods: {
init () {
const meta = this.metaList[this.metaIndex]
const params = meta.parameter_set
this.content += 'Duration: ' + parseInt(parseInt(meta.time_duration / 1000000) / 60) + ' m ' + parseInt((meta.time_duration % 60000000) / 1000000) + ' s<br/>'
this.content += '<br/>Parameter: <br/>'
this.content += '<br/> Recording: <br/>'
if (this.deviceName === 'neulive') {
// recording param
for (const [key, value] of Object.entries(params)) {
if (!(key.includes('sti') || key.includes('STI'))) {
let showKey = ''
let showValue = value
if (key === 'RECORDING_CH' || key === 'AXIS_CH' || key === 'AMP_GAIN' || key === 'ADC_CLOCK') {
if (key === 'RECORDING_CH') {
showKey = 'Channels'
// convert decimal to binary
const binaryChannelValue = showValue.toString(2)
const channelValue = binaryChannelValue.split('')
showValue = ''
channelValue.forEach(function (value, i) {
if (value === '1') {
showValue += `${i + 1} `
}
})
if (showValue === '') {
showValue = 'None'
}
} else if (key === 'AXIS_CH') {
showKey = '3-AXIS'
// convert decimal to binary
const binaryChannelValue = showValue.toString(2)
const channelValue = binaryChannelValue.split('').reverse()
showValue = ''
channelValue.forEach(function (value, i) {
if (value === '1') {
if (i === 0) {
showValue += 'x '
} else if (i === 1) {
showValue += 'y '
} else if (i === 2) {
showValue += 'z '
} else if (i === 3) {
showValue += 'mag '
}
}
})
if (showValue === '') {
showValue = 'None'
}
} else if (key === 'AMP_GAIN') {
showKey = 'Amp gain'
const targetID = (value + 1) % 4
for (let i = 0; i < this.ampGainOptions.length; i++) {
if (this.ampGainOptions[i].id === targetID) {
showValue = this.ampGainOptions[i].description
}
}
} else if (key === 'ADC_CLOCK') {
showKey = 'Sample Rate'
for (let i = 0; i < this.neuliveSampleRateOptions.length; i++) {
if (this.neuliveSampleRateOptions[i].value === value) {
showValue = this.neuliveSampleRateOptions[i].description
}
}
}
this.content += ' ' + showKey + ': ' + showValue + '<br/>'
}
}
}
// stimulation param
this.content += '<br/> Stimulation: <br/>'
for (const [key, value] of Object.entries(params)) {
if (key.includes('sti') || key.includes('STI')) {
let showKey = ''
let showValue = value
if (key === 'STI_H_BRIDGE' || key === 'STI_CHANNEL' || key === 'STI_POLARITY' || key === 'CONTINUOUS_STI' ||
key === 'STI_AMPLITUDE' || key === 'STI_PATTERN' || key === 'STI_T1' || key === 'STI_T2' || key === 'STI_T3' || key === 'STI_T4') {
if (key === 'STI_H_BRIDGE') {
showKey = 'ELECTRODE'
if (value === true) {
showValue = this.stimulateElectrodeOptions[1].label
} else {
showValue = this.stimulateElectrodeOptions[0].label
}
} else if (key === 'STI_CHANNEL' || key === 'STI_POLARITY') {
if (key === 'STI_CHANNEL') {
showKey = 'Channels'
} else {
showKey = 'Polarity'
}
// convert decimal to binary
const binaryChannelValue = showValue.toString(2)
const channelValue = binaryChannelValue.split('')
showValue = ''
channelValue.forEach(function (value, i) {
if (value === '1') {
showValue += `${i + 1} `
}
})
if (showValue === '') {
showValue = 'None'
}
} else if (key === 'CONTINUOUS_STI') {
showKey = 'CYCLE NUMBER'
if (value === true) {
showValue = this.cycleNumberOptions[1].label
} else {
showValue = this.cycleNumberOptions[0].label
}
} else if (key === 'STI_AMPLITUDE') {
showKey = 'AMPLITUDE (uA)'
showValue = value * 5
} else if (key === 'STI_PATTERN') {
showKey = 'PATTERN'
if (value === true) {
showValue = this.patternModeOptions[1].label
} else {
showValue = this.patternModeOptions[0].label
}
} else if (key === 'STI_T1') {
showKey = 'T1 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us, [0] is cuz now all values in array are same
} else if (key === 'STI_T2') {
showKey = 'T2 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us
} else if (key === 'STI_T3') {
showKey = 'T3 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us
} else if (key === 'STI_T4') {
showKey = 'T4 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us
}
this.content += ' ' + showKey + ': ' + showValue + '<br/>'
}
}
}
if ('STI_T1' in params && 'STI_T2' in params && 'STI_T3' in params && 'STI_T4' in params) {
const period = (params.STI_T1[0] + params.STI_T2[0] + params.STI_T3[0] + params.STI_T4[0]) * 10 / 1000 // 10 is cuz 1 value = 10us
this.content += ' Frequency: ' + String(1000 / period) + ' Hz' + '<br/>' // 1000 is cuz 1s = 1000ms
this.content += ' Period: ' + String(period) + ' ms' + '<br/>'
}
} else if (this.deviceName === 'elite') {
for (const [key, value] of Object.entries(params)) {
let showKey = ''
let showValue = value
if (key === 'MODE') {
showKey = 'MODE'
for (let i = 0; i < this.workingModeOptions.length; i++) {
if (this.workingModeOptions[i].id === value) {
showValue = this.workingModeOptions[i].description
}
}
} else if (key === 'ADC_LEVEL') {
showKey = 'Current Range'
for (let i = 0; i < this.currentRangeOptions.length; i++) {
if (this.currentRangeOptions[i].value === value) {
showValue = this.currentRangeOptions[i].label
}
}
} else if (key === 'VOLT_ORIGIN') {
showKey = 'Volt start'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'VOLT_FINAL') {
showKey = 'Volt stop'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'VOLT_STEP') {
showKey = 'Volt step'
showValue = ((value * 2) + 2) / 10 + 'mV'
} else if (key === 'STEP_TIME') {
showKey = 'Step time'
for (let i = 0; i < this.stepTimeOptions.length; i++) {
if (this.stepTimeOptions[i].value === value) {
showValue = this.stepTimeOptions[i].label
}
}
} else if (key === 'CYCLE_NUMBER') {
showKey = 'Cycle number'
showValue = value
} else if (key === 'DAC_VOLT') {
showKey = 'Volt out'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'Resister_LEVEL') {
showKey = 'Resister Range'
for (let i = 0; i < this.resisterRangeOptions.length; i++) {
if (this.resisterRangeOptions[i].value === value) {
showValue = this.resisterRangeOptions[i].label
}
}
} else if (key === 'SAMPLE_RATE') {
showKey = 'Sample rate'
for (let i = 0; i < this.eliteSampleRateOptions.length; i++) {
if (this.eliteSampleRateOptions[i].value === value) {
showValue = this.eliteSampleRateOptions[i].label
}
}
} else if (key === 'Const_Current_value') {
showKey = 'Current'
showValue = value + 'μA'
} else if (key === 'VOLTSTOP_MAX') {
showKey = 'Volt max stop'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'VOLTSTOP_MIN') {
showKey = 'Volt min stop'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'Charge') {
showKey = 'Charge'
for (let i = 0; i < this.chargeOptions.length; i++) {
if (this.chargeOptions[i].value === value) {
showValue = this.chargeOptions[i].label
}
}
} else if (key === 'VOLT_INITIAL') {
showKey = 'E-Initial'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'VOLT_MAX') {
showKey = 'Volt max stop'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'VOLT_MIN') {
showKey = 'Volt min stop'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'Scan_Rate') {
showKey = 'ScanRate'
showValue = (value / 100) + 0.01 + 'mV/s'
} else if (key === 'Data_Resolution_Scan') {
showKey = 'Resolution'
showValue = (value / 10) + 0.1 + 'sps'
} else if (key === 'VOLT_EFINAL') {
showKey = 'E-Final'
showValue = (value / 5000) - 5 + 'V'
} else if (key === 'VOLT_VSCAN') {
showKey = 'VScan'
showValue = (value / 5000) - 5 + 'V'
} else {
continue
}
this.content += ' ' + showKey + ': ' + showValue + '<br/>'
}
}
},
},
}
</script>
@@ -0,0 +1,37 @@
<template>
<div>
<span> Resample: {{ currentScale }} to 1 </span>
</div>
</template>
<script>
import { mapFields } from 'vuex-map-fields'
export default {
name: 'show-resample-rate',
components: {
},
props: {
},
created () {
},
data () {
return {
}
},
computed: {
...mapFields('replay', [
'currentScale',
]),
},
watch: {
},
methods: {
},
mounted () {
},
destroyed () {
},
}
</script>
+22 -10
View File
@@ -86,7 +86,7 @@
<div>
<va-button style="width: 100px;" @click.stop="connect(controller.id, device)" v-if="device.status == 'scanned' && !device.loading" class="pl-2 pr-2 mt-2" color="success" small>CONNECT</va-button>
<va-button style="width: 100px;" @click.stop="disconnectCheck(controller.id, device)" :disabled="controller.isScan" v-if="device.status == 'connected' && !device.loading" class="pl-2 pr-2 mt-2" color="danger" small>DISCONNECT</va-button>
<va-button @click.stop="detect(controller.id, device)" :disabled="controller.isScan" v-if="device.status == 'connected' && !device.loading && device.library_name.indexOf('Elite') !== -1" class="pl-2 pr-2 mt-2" color="primary" small>DETECT</va-button>
<va-button id="detectButton" @click.stop="detect(controller.id, device)" :disabled="controller.isScan" v-if="device.status == 'connected' && !device.loading && device.library_name.indexOf('Elite') !== -1" class="pl-2 pr-2 mt-2" color="primary" small>DETECT</va-button>
</div>
</va-item-section>
</va-item>
@@ -137,9 +137,9 @@
</template>
<script>
import api from '@/data/api/index'
import { taskInfo } from '../../data/task/TaskInfo'
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
import api from '../../data/api/index'
export default {
name: 'devices-overview',
@@ -208,16 +208,27 @@ export default {
})
// console.log(this.controllerList)
},
'+/hardware_info/+' (data, topic) {
async '+/hardware_info/+' (data, topic) {
const topicSplit = topic.split('/')
const rawDevices = JSON.parse(String.fromCharCode.apply(null, data)).data
this.controllerList.forEach(controller => {
for (let i = 0; i < this.controllerList.length; i++) {
const controller = this.controllerList[i]
if (controller.id === topicSplit[0]) {
if (rawDevices.device_mac !== null) {
controller.mac = rawDevices.device_mac.toUpperCase()
// const info = await api.controller.getByMac(controller.mac)
// if (info.data.length === 0) {
// const req = {
// mac_address: controller.mac,
// mqtt_id: controller.id,
// status: controller.status,
// }
// api.controller.create(req)
// }
// console.log(info)
}
}
})
}
// console.log(this.controllerList)
},
'+/hardware_device_connect/+' (data, topic) {
@@ -459,6 +470,7 @@ export default {
device: device.id,
instruction: 'VIS_DEVICE_DONE',
}))
document.getElementById('detectButton').className += ' no-dark-style-va-button'
}, 5000)
},
sleep: function (milliseconds) {
@@ -470,9 +482,9 @@ export default {
}
},
createInitialCollection: async function (user) {
const root = await api.getCollectionsByParentName('folder', 0, 'root')
const root = await api.collection.getByParentName('folder', 0, 'root')
if (root.data.length === 0) {
await api.createCollection({
await api.collection.create({
name: 'root',
type: 'folder',
parent: { folder: [0] },
@@ -481,10 +493,10 @@ export default {
}
// init check and create collection
const _root = await api.getCollectionsByName('root')
const USER = await api.getCollectionsByName(user)
const _root = await api.collection.getByName('root')
const USER = await api.collection.getByName(user)
if (USER.data.length === 0) {
api.createCollection({
api.collection.create({
name: user,
parent: { folder: [_root.data[0].id] },
type: 'folder',
@@ -0,0 +1,159 @@
<template>
<div>
</div>
</template>
<script>
import api from '@/data/api/index'
import types from '@/store/modules/file/elite/csv/types'
import { mapActions, mapGetters, mapMutations } from 'vuex'
// import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
export default {
name: 'Download',
components: {
// FulfillingBouncingCircleSpinner,
},
data: () => {
return {
controllerList: [],
spliceDataNumsLimit: 20,
}
},
computed: {
getByIndex (index) {
return this.getByIndexDownload(index)
},
getDownloading () {
return this.getDownloadingDownload()
},
getRemainIDLength (index) {
return this.getRemainIDLengthDownload(index)
},
},
methods: {
getControllerList: async function () {
const update = async () => {
this.controllerList.push({
id: 'tommy_test',
mac: '',
status: 'loading',
isScan: true,
files: [],
})
}
await update()
},
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
mqttSub: function (val) {
this.$mqtt.subscribe(val)
},
mqttUnSub: function (val) {
this.$mqtt.unsubscribe(val)
},
pageMqttSub: function () {
this.controllerList.forEach(controller => {
// this.mqttSub(controller.id + '/broadcast')
this.mqttSub(controller.id + '/file_meta_info/+')
this.mqttSub(controller.id + '/file_segment/+')
this.mqttSub(controller.id + '/file_segment_get/+')
})
},
pageMqttUnSub: function () {
this.controllerList.forEach(controller => {
// this.mqttUnSub(controller.id + '/broadcast')
this.mqttUnSub(controller.id + '/file_meta_info/+')
this.mqttUnSub(controller.id + '/file_segment/+')
this.mqttUnSub(controller.id + '/file_segment_get/+')
})
},
notify (name) {
this.showToast(`done ${name}`, {
position: 'bottom-right',
})
},
...mapActions('eliteCsv',
[
types.download.init,
types.download.rawDataByIDs,
types.export.createHeadersString,
types.export.createTitlesString,
types.export.createDataString,
types.export.closeFileStream,
],
),
...mapMutations('eliteCsv',
[
types.download.setDownloading,
types.download.removeDownloadBuffer,
],
),
...mapGetters('eliteCsv',
[
types.download.getByIndex,
types.download.getDownloading,
types.download.getAll,
types.download.getRemainIDLength,
],
),
},
watch: {
},
async mounted () {
await this.getControllerList()
// TODO authorization
this.pageMqttSub()
const metaIDList = this.$route.params.metaList.split('-')
const recoverData = this.$route.params.recover
await this.initDownload({ metaIDList: metaIDList, api: api })
// let first file download in download List
this.setDownloadingDownload()
const downloadingFile = this.getDownloading
downloadingFile.recoverData = recoverData
let spliceDataNums = 0
// console.log('downloadingFile', downloadingFile)
// console.log(this.getRemainIDLength(0))
// create headers and title
this.createHeadersStringExport()
this.createTitlesStringExport()
// loop until each channel's rawID List empty
while (this.getRemainIDLength(0)) {
// forEach channel in raw_data
for (const channel in downloadingFile.raw_data) {
// get spliceDataNumsLimit numbers of ID to download once time
if (downloadingFile.raw_data[channel].length >= this.spliceDataNumsLimit) {
spliceDataNums = this.spliceDataNumsLimit
} else {
spliceDataNums = downloadingFile.raw_data[channel].length
}
const rawID = downloadingFile.raw_data[channel].splice(0, spliceDataNums)
// console.log('rawID', channel, rawID)
// download data and save into dataBuffer by rawDataIDList
await this.rawDataByIDsDownload({
channel: channel,
rawDataIDList: rawID,
api: api,
})
}
// export data
this.createDataStringExport()
// this.removeDownloadBufferDownload()
}
this.closeFileStreamExport()
},
destroyed () {
this.pageMqttUnSub()
},
}
</script>
<style>
.filter-button {
text-align: center;
}
</style>
@@ -0,0 +1,207 @@
<template>
<div>
</div>
</template>
<script>
import api from '@/data/api/index'
import types from '@/store/modules/file/elite/excel/types'
import { mapActions, mapGetters, mapMutations } from 'vuex'
// import { file } from '../../data/file/File'
// import { download } from '../../data/download/Download'
// import { exportData } from '../../data/export/export'
// import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
export default {
name: 'Download',
components: {
// FulfillingBouncingCircleSpinner,
},
data: () => {
return {
controllerList: [],
}
},
computed: {
getByIndex (index) {
return this.getByIndexDownload(index)
},
getDownloading () {
return this.getDownloadingDownload()
},
getRemainIDLength (index) {
return this.getRemainIDLengthDownload(index)
},
// transTime (min,max) {
// return this.getTimeInFormat(min) + ' - ' + this.getTimeInFormat(max)
// },
loaded () {
return this.loadingPercent + '%'
},
},
methods: {
transTime (timeRange) {
return this.getTimeInFormat(timeRange[0]) + ' - ' + this.getTimeInFormat(timeRange[1])
},
notify (name) {
this.showToast(`done ${name}`, {
position: 'bottom-right',
})
},
getControllerList: async function () {
const update = async () => {
this.controllerList.push({
id: 'tommy_test',
mac: '',
status: 'loading',
isScan: true,
files: [],
})
}
await update()
},
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
mqttSub: function (val) {
this.$mqtt.subscribe(val)
},
mqttUnSub: function (val) {
this.$mqtt.unsubscribe(val)
},
pageMqttSub: function () {
this.controllerList.forEach(controller => {
// this.mqttSub(controller.id + '/broadcast')
this.mqttSub(controller.id + '/file_meta_info/+')
this.mqttSub(controller.id + '/file_segment/+')
this.mqttSub(controller.id + '/file_segment_get/+')
})
},
pageMqttUnSub: function () {
this.controllerList.forEach(controller => {
// this.mqttUnSub(controller.id + '/broadcast')
this.mqttUnSub(controller.id + '/file_meta_info/+')
this.mqttUnSub(controller.id + '/file_segment/+')
this.mqttUnSub(controller.id + '/file_segment_get/+')
})
},
...mapActions('eliteExcel',
[
types.download.init,
types.download.rawDataByIDs,
types.export.createHeadersString,
types.export.createTitlesString,
types.export.createDataString,
types.export.closeFileStream,
],
),
...mapMutations('eliteExcel',
[
types.download.setDownloading,
types.download.removeDownloadBuffer,
],
),
...mapGetters('eliteExcel',
[
types.download.getByIndex,
types.download.getDownloading,
types.download.getAll,
types.download.getRemainIDLength,
],
),
},
openPortal () {
this.windowRef = window.open('', '', 'width=600,height=400,left=200,top=200')
this.windowRef.document.body.appendChild(this.$el)
// copyStyles(window.document, this.windowRef.document)
this.windowRef.addEventListener('beforeunload', this.closePortal)
},
closePortal () {
if (this.windowRef) {
this.windowRef.close()
this.windowRef = null
this.$emit('close')
}
},
// watch: {
// loadingPercent(val) {
// if (val >= 100) {
// console.log('complete');
// clearInterval(this.interval)
// }
// }
// },
async mounted () {
await this.getControllerList()
// TODO authorization
this.pageMqttSub()
const metaIDList = this.$route.params.metaList.split('-')
await this.initDownload({ metaIDList: metaIDList, api: api })
this.setDownloadingDownload()
const downloadingFile = this.getDownloading
console.log('downloadingFile', downloadingFile)
console.log(this.getRemainIDLength(0))
// create headers and title
this.createHeadersStringExport()
this.createTitlesStringExport()
// let spliceDataNums = 0
let rowIndex = 0
// let columnIndex = 0
// // while (this.getRemainIDLength(0)) {
while (rowIndex < downloadingFile.needRows) {
for (const channel in downloadingFile.downloadIDList) {
const rawID = downloadingFile.downloadIDList[channel][rowIndex]
// console.log('rawID', channel, rawID)
if (rawID !== undefined) {
await this.rawDataByIDsDownload({
channel: channel,
rawDataIDList: rawID,
api: api,
})
}
}
this.createDataStringExport()
this.removeDownloadBufferDownload()
// console.log('end', downloadingFile)
rowIndex += 1
}
this.closeFileStreamExport()
// }
// if (downloadingFile.raw_data[channel].length >= 10) {
// spliceDataNums = 10
// } else {
// spliceDataNums = downloadingFile.raw_data[channel].length
// }
// const rawID = downloadingFile.raw_data[channel].splice(0, spliceDataNums)
// console.log('rawID', channel, rawID)
// await this.rawDataByIDsDownload({
// channel: channel,
// rawDataIDList: rawID,
// api: api,
// })
// }
// // console.log('end', downloadingFile)
// // export data
// this.createDataStringExport({})
// this.removeDownloadBufferDownload()
// }
// const rawData = await download.getAllRawDatas(meta.data[0])
// exportData.exportCSV(meta.data[0], rawData)
// await this.initMeta({ metaIDList: metaIDList, api: api })
},
destroyed () {
this.pageMqttUnSub()
},
}
</script>
<style>
.filter-button {
text-align: center;
}
</style>
@@ -0,0 +1,159 @@
<template>
<div>
</div>
</template>
<script>
import api from '@/data/api/index'
import types from '@/store/modules/file/neulive/csv/types'
import { mapActions, mapGetters, mapMutations } from 'vuex'
// import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
export default {
name: 'Download',
components: {
// FulfillingBouncingCircleSpinner,
},
data: () => {
return {
controllerList: [],
spliceDataNumsLimit: 20,
}
},
computed: {
getByIndex (index) {
return this.getByIndexDownload(index)
},
getDownloading () {
return this.getDownloadingDownload()
},
getRemainIDLength (index) {
return this.getRemainIDLengthDownload(index)
},
},
methods: {
getControllerList: async function () {
const update = async () => {
this.controllerList.push({
id: 'tommy_test',
mac: '',
status: 'loading',
isScan: true,
files: [],
})
}
await update()
},
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
mqttSub: function (val) {
this.$mqtt.subscribe(val)
},
mqttUnSub: function (val) {
this.$mqtt.unsubscribe(val)
},
pageMqttSub: function () {
this.controllerList.forEach(controller => {
// this.mqttSub(controller.id + '/broadcast')
this.mqttSub(controller.id + '/file_meta_info/+')
this.mqttSub(controller.id + '/file_segment/+')
this.mqttSub(controller.id + '/file_segment_get/+')
})
},
pageMqttUnSub: function () {
this.controllerList.forEach(controller => {
// this.mqttUnSub(controller.id + '/broadcast')
this.mqttUnSub(controller.id + '/file_meta_info/+')
this.mqttUnSub(controller.id + '/file_segment/+')
this.mqttUnSub(controller.id + '/file_segment_get/+')
})
},
notify (name) {
this.showToast(`done ${name}`, {
position: 'bottom-right',
})
},
...mapActions('neuliveCsv',
[
types.download.init,
types.download.rawDataByIDs,
types.export.createHeadersString,
types.export.createTitlesString,
types.export.createDataString,
types.export.closeFileStream,
],
),
...mapMutations('neuliveCsv',
[
types.download.setDownloading,
types.download.removeDownloadBuffer,
],
),
...mapGetters('neuliveCsv',
[
types.download.getByIndex,
types.download.getDownloading,
types.download.getAll,
types.download.getRemainIDLength,
],
),
},
watch: {
},
async mounted () {
await this.getControllerList()
// TODO authorization
this.pageMqttSub()
const metaIDList = this.$route.params.metaList.split('-')
const recoverData = this.$route.params.recover
await this.initDownload({ metaIDList: metaIDList, api: api })
// let first file download in download List
this.setDownloadingDownload()
const downloadingFile = this.getDownloading
downloadingFile.recoverData = recoverData
let spliceDataNums = 0
// console.log('downloadingFile', downloadingFile)
// console.log(this.getRemainIDLength(0))
// create headers and title
this.createHeadersStringExport()
this.createTitlesStringExport()
// loop until each channel's rawID List empty
while (this.getRemainIDLength(0)) {
// forEach channel in raw_data
for (const channel in downloadingFile.raw_data) {
// get spliceDataNumsLimit numbers of ID to download once time
if (downloadingFile.raw_data[channel].length >= this.spliceDataNumsLimit) {
spliceDataNums = this.spliceDataNumsLimit
} else {
spliceDataNums = downloadingFile.raw_data[channel].length
}
const rawID = downloadingFile.raw_data[channel].splice(0, spliceDataNums)
// console.log('rawID', channel, rawID)
// download data and save into dataBuffer by rawDataIDList
await this.rawDataByIDsDownload({
channel: channel,
rawDataIDList: rawID,
api: api,
})
}
// export data
this.createDataStringExport()
// this.removeDownloadBufferDownload()
}
this.closeFileStreamExport()
},
destroyed () {
this.pageMqttUnSub()
},
}
</script>
<style>
.filter-button {
text-align: center;
}
</style>
@@ -0,0 +1,207 @@
<template>
<div>
</div>
</template>
<script>
import api from '@/data/api/index'
import types from '@/store/modules/file/neulive/excel/types'
import { mapActions, mapGetters, mapMutations } from 'vuex'
// import { file } from '../../data/file/File'
// import { download } from '../../data/download/Download'
// import { exportData } from '../../data/export/export'
// import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
export default {
name: 'Download',
components: {
// FulfillingBouncingCircleSpinner,
},
data: () => {
return {
controllerList: [],
}
},
computed: {
getByIndex (index) {
return this.getByIndexDownload(index)
},
getDownloading () {
return this.getDownloadingDownload()
},
getRemainIDLength (index) {
return this.getRemainIDLengthDownload(index)
},
// transTime (min,max) {
// return this.getTimeInFormat(min) + ' - ' + this.getTimeInFormat(max)
// },
loaded () {
return this.loadingPercent + '%'
},
},
methods: {
transTime (timeRange) {
return this.getTimeInFormat(timeRange[0]) + ' - ' + this.getTimeInFormat(timeRange[1])
},
notify (name) {
this.showToast(`done ${name}`, {
position: 'bottom-right',
})
},
getControllerList: async function () {
const update = async () => {
this.controllerList.push({
id: 'tommy_test',
mac: '',
status: 'loading',
isScan: true,
files: [],
})
}
await update()
},
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
mqttSub: function (val) {
this.$mqtt.subscribe(val)
},
mqttUnSub: function (val) {
this.$mqtt.unsubscribe(val)
},
pageMqttSub: function () {
this.controllerList.forEach(controller => {
// this.mqttSub(controller.id + '/broadcast')
this.mqttSub(controller.id + '/file_meta_info/+')
this.mqttSub(controller.id + '/file_segment/+')
this.mqttSub(controller.id + '/file_segment_get/+')
})
},
pageMqttUnSub: function () {
this.controllerList.forEach(controller => {
// this.mqttUnSub(controller.id + '/broadcast')
this.mqttUnSub(controller.id + '/file_meta_info/+')
this.mqttUnSub(controller.id + '/file_segment/+')
this.mqttUnSub(controller.id + '/file_segment_get/+')
})
},
...mapActions('neuliveExcel',
[
types.download.init,
types.download.rawDataByIDs,
types.export.createHeadersString,
types.export.createTitlesString,
types.export.createDataString,
types.export.closeFileStream,
],
),
...mapMutations('neuliveExcel',
[
types.download.setDownloading,
types.download.removeDownloadBuffer,
],
),
...mapGetters('neuliveExcel',
[
types.download.getByIndex,
types.download.getDownloading,
types.download.getAll,
types.download.getRemainIDLength,
],
),
},
openPortal () {
this.windowRef = window.open('', '', 'width=600,height=400,left=200,top=200')
this.windowRef.document.body.appendChild(this.$el)
// copyStyles(window.document, this.windowRef.document)
this.windowRef.addEventListener('beforeunload', this.closePortal)
},
closePortal () {
if (this.windowRef) {
this.windowRef.close()
this.windowRef = null
this.$emit('close')
}
},
// watch: {
// loadingPercent(val) {
// if (val >= 100) {
// console.log('complete');
// clearInterval(this.interval)
// }
// }
// },
async mounted () {
await this.getControllerList()
// TODO authorization
this.pageMqttSub()
const metaIDList = this.$route.params.metaList.split('-')
await this.initDownload({ metaIDList: metaIDList, api: api })
this.setDownloadingDownload()
const downloadingFile = this.getDownloading
console.log('downloadingFile', downloadingFile)
console.log(this.getRemainIDLength(0))
// create headers and title
this.createHeadersStringExport()
this.createTitlesStringExport()
// let spliceDataNums = 0
let rowIndex = 0
// let columnIndex = 0
// // while (this.getRemainIDLength(0)) {
while (rowIndex < downloadingFile.needRows) {
for (const channel in downloadingFile.downloadIDList) {
const rawID = downloadingFile.downloadIDList[channel][rowIndex]
// console.log('rawID', channel, rawID)
if (rawID !== undefined) {
await this.rawDataByIDsDownload({
channel: channel,
rawDataIDList: rawID,
api: api,
})
}
}
this.createDataStringExport()
this.removeDownloadBufferDownload()
// console.log('end', downloadingFile)
rowIndex += 1
}
this.closeFileStreamExport()
// }
// if (downloadingFile.raw_data[channel].length >= 10) {
// spliceDataNums = 10
// } else {
// spliceDataNums = downloadingFile.raw_data[channel].length
// }
// const rawID = downloadingFile.raw_data[channel].splice(0, spliceDataNums)
// console.log('rawID', channel, rawID)
// await this.rawDataByIDsDownload({
// channel: channel,
// rawDataIDList: rawID,
// api: api,
// })
// }
// // console.log('end', downloadingFile)
// // export data
// this.createDataStringExport({})
// this.removeDownloadBufferDownload()
// }
// const rawData = await download.getAllRawDatas(meta.data[0])
// exportData.exportCSV(meta.data[0], rawData)
// await this.initMeta({ metaIDList: metaIDList, api: api })
},
destroyed () {
this.pageMqttUnSub()
},
}
</script>
<style>
.filter-button {
text-align: center;
}
</style>
+6 -7
View File
@@ -5,7 +5,7 @@
<file-table :ref="'file_ref'" @download="addDownloadTask"/>
</div>
<div class="flex md12 xl12 xs12 sm12" :style="AreaStyle">
<download :ref="'download_ref'" @download="downloadingFile"></download>
<!-- <download :ref="'download_ref'" @download="downloadingFile"></download> -->
</div>
</div>
</div>
@@ -13,14 +13,13 @@
<script>
import FileTable from './file-table/FileTable.vue'
import Download from '../download/Download.vue'
// import Download from '../download/Download.vue'
import { file } from '../../data/file/File'
import api from '../../data/api/index'
export default {
components: {
FileTable,
Download,
},
data () {
return {
@@ -71,15 +70,15 @@ export default {
this.$refs.file_ref.currentPathIndex = file.getPathMaxIndex()
file.clearFileList()
const initCollection = await api.getCollectionsByName('admin')
const initCollection = await api.collection.getByName('admin')
if (initCollection.data !== 0) {
file.addPath(initCollection.data[0])
this.$refs.file_ref.currentPathIndex = file.getPathMaxIndex()
this.$refs.file_ref.currentInfo = initCollection.data[0]
const folders = await api.getCollectionsByParent('folder', initCollection.data[0].id)
const files = await api.getFolderMetaFileByParent('folder', initCollection.data[0].id)
const folders = await api.collection.getByParent('folder', initCollection.data[0].id)
const files = await api.meta.getCollectionByParent('folder', initCollection.data[0].id)
file.updateFileList(folders)
file.updateFileList(files)
@@ -92,7 +91,7 @@ export default {
},
async mounted () {
await this.getControllerList()
await api.getJwtData()
await api.auth.getJwtData()
this.pageMqttSub()
this.pageInitPub()
},
+81 -45
View File
@@ -52,16 +52,16 @@
</va-modal>
<va-card class="flex sm12 xl12 md12 xs12">
<!-- <template slot="header">
<template slot="header">
<div class="flex sm12 xl12 md12 xs12" style="text-align: end;">
<va-button class="" color="success" v-if="selected.length" @click="showrefs" target="_blank" small>
<!-- <va-button class="" color="success" v-if="selected.length" @click="downloadSelected" target="_blank" small>
DOWNLOAD
</va-button>
<va-button class="" color="danger" v-if="selected.length" target="_blank" small>
</va-button> -->
<va-button class="" color="danger" v-if="selected.length" @click="deleteSelected" target="_blank" small>
DELETE
</va-button>
</div>
</template> -->
</template>
<!-- SearchField & perPageSelect-->
<div class="row align--center">
@@ -137,9 +137,9 @@
v-else
:ref="'datatable_ref'"
>
<!-- <template slot="select" slot-scope="props">
<template slot="select" slot-scope="props">
<va-checkbox :value="props.rowData.checked" @input="select(props.rowData)"/>
</template> -->
</template>
<template slot="name" slot-scope="props">
<va-icon
:name="(props.rowData.type==='folder')?'fa fa-folder':'fa fa-file'"
@@ -163,8 +163,11 @@
{{transDeviceInfo(props.rowData.configuration)}}
</template>
<template slot="actions" slot-scope="props" >
<va-popover :message="`download ${props.rowData.name}`" placement="top">
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder'" @click.stop="download(props.rowData)"/>
<va-popover :message="`download ${props.rowData.name} in csv format`" placement="top">
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder'" @click.stop="downloadCsv(props.rowData)"/>
</va-popover>
<va-popover :message="`download ${props.rowData.name} in excel format`" placement="top">
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder'" @click.stop="downloadExcel(props.rowData)"/>
</va-popover>
<va-popover :message="`replay ${props.rowData.name}`" placement="top">
<va-button flat small color="gray" icon="fa fa-eye" v-if="props.rowData.type !== 'folder'" @click.stop="replay(props.rowData)"/>
@@ -246,14 +249,15 @@ export default {
computed: {
fields () {
return [
// {
// name: '__slot:select',
// },
{
name: '__slot:select',
width: '5%',
},
{
name: '__slot:name',
title: 'name',
sortField: 'name',
width: '20%',
width: '15%',
titleClass: 'text-center',
},
// {
@@ -295,7 +299,7 @@ export default {
{
name: '__slot:actions',
dataClass: 'text-right',
width: '15%',
width: '20%',
},
]
},
@@ -364,8 +368,8 @@ export default {
this.currentPathIndex = file.getPathMaxIndex()
// call getfolder api and update
const folders = await api.getCollectionsByParent('folder', info.id)
const files = await api.getFolderMetaFileByParent('folder', info.id)
const folders = await api.collection.getByParent('folder', info.id)
const files = await api.meta.getCollectionByParent('folder', info.id)
file.updateFileList(folders)
file.updateFileList(files)
@@ -384,8 +388,8 @@ export default {
this.currentPathIndex = file.getPathMaxIndex()
this.currentInfo = item
// call getfolder api and update
const folders = await api.getCollectionsByParent('folder', item.id)
const files = await api.getFolderMetaFileByParent('folder', item.id)
const folders = await api.collection.getByParent('folder', item.id)
const files = await api.meta.getCollectionByParent('folder', item.id)
file.updateFileList(folders)
file.updateFileList(files)
@@ -401,12 +405,12 @@ export default {
this.currentPathIndex = -1
// call getfolder api and update
const initCollection = await api.getCollectionsByParentName('folder', 0, 'root')
const initCollection = await api.collection.getByParentName('folder', 0, 'root')
if (initCollection.data.length === 1) {
this.currentInfo = initCollection.data[0]
const folders = await api.getCollectionsByParent('folder', initCollection.data[0].id)
const files = await api.getFolderMetaFileByParent('folder', initCollection.data[0].id)
const folders = await api.collection.getByParent('folder', initCollection.data[0].id)
const files = await api.meta.getCollectionByParent('folder', initCollection.data[0].id)
file.updateFileList(folders)
file.updateFileList(files)
this.fileLists = file.getFileList()
@@ -424,7 +428,7 @@ export default {
this.setInputFieldError(this.createInfo.errorMessagesAll[0] + ' ' + illegalChar[0], this.createInfo)
} else {
// folder name existed
const existedFolder = await api.getCollectionsByParentName(this.currentInfo.type, this.currentInfo.id, term)
const existedFolder = await api.collection.getByParentName(this.currentInfo.type, this.currentInfo.id, term)
if (existedFolder.data.length === 0) {
this.setInputFieldSuccess(this.createInfo)
} else {
@@ -440,7 +444,7 @@ export default {
createFolder: async function () {
const parent = [].concat((this.pathLists.length === 0) ? this.currentInfo.id : this.pathLists[this.pathLists.length - 1].id)
const type = 'folder'
await api.createCollection({
await api.collection.create({
name: this.createInfo.changedName,
parent: { [type]: parent },
type: type,
@@ -465,7 +469,7 @@ export default {
editFile: async function () {
// TODO editFile
if (this.editInfo.type !== 'folder') {
await api.updateMetaFile(this.editInfo.info.id, { name: this.editInfo.changedName })
await api.meta.update(this.editInfo.info.id, { name: this.editInfo.changedName })
} else {
}
await this.editFileDone()
@@ -523,8 +527,7 @@ export default {
},
removeFileFromList: function () {
},
deleteFileConfirm: function (info) {
// console.log(info)
fillDeleteInfo (info) {
this.deleteInfo.path = info.path
this.deleteInfo.name = info.name
this.deleteInfo.metaID = info.id
@@ -538,26 +541,29 @@ export default {
this.deleteInfo.miniChannelAndIDArrays.push([channel, idArray[0]])
}
}
// console.log(this.deleteInfo.rawChannelAndIDArrays)
// console.log(this.deleteInfo.miniChannelAndIDArrays)
// console.log(this.deleteInfo.metaID)
this.showModal.deleteFile = true
},
deleteFile: async function () {
async deleteSingleFileByDeleteInfo () {
for (const item of this.deleteInfo.rawChannelAndIDArrays) {
const channel = item[0]
const id = item[1]
await api.updateRawFile(channel, id, { deleted: true })
await api.clearDeleteRawFile(channel, id)
await api.raw.update(channel, id, { deleted: true })
await api.raw.clearDel(channel, id)
}
for (const item of this.deleteInfo.miniChannelAndIDArrays) {
const channel = item[0]
const id = item[1]
await api.updateMiniFile(channel, id, { deleted: true })
await api.clearDeleteMiniFile(channel, id)
await api.mini.update(channel, id, { deleted: true })
await api.mini.clearDel(channel, id)
}
await api.updateMetaFile(this.deleteInfo.metaID, { deleted: true })
await api.clearDeleteMetaFile(this.deleteInfo.metaID)
await api.meta.update(this.deleteInfo.metaID, { deleted: true })
await api.meta.clearDel(this.deleteInfo.metaID)
},
deleteFileConfirm: function (info) {
this.fillDeleteInfo(info)
this.showModal.deleteFile = true
},
deleteFile: async function () {
await this.deleteSingleFileByDeleteInfo()
await this.deleteFileDone()
},
deleteFileDone: async function () {
@@ -597,8 +603,8 @@ export default {
file.clearFileList()
// call getfolder api and update
const folders = await api.getCollectionsByParent('folder', this.currentInfo.id)
const files = await api.getFolderMetaFileByParent('folder', this.currentInfo.id)
const folders = await api.collection.getByParent('folder', this.currentInfo.id)
const files = await api.meta.getCollectionByParent('folder', this.currentInfo.id)
file.updateFileList(folders)
file.updateFileList(files)
@@ -608,17 +614,47 @@ export default {
// this.$refs.datatable_ref.refresh()
// this.$refs.datatable_ref.currentPage = 1
},
showrefs: function () {
this.$emit('download', this.selected)
// downloadSelected: function () {
// for (let i = 0; i < this.selected.length; i++) {
// const meta = this.selected[i]
// this.downloadCsv(meta)
// }
// },
async deleteSelected () {
for (let i = 0; i < this.selected.length; i++) {
const meta = this.selected[i]
this.fillDeleteInfo(meta)
await this.deleteSingleFileByDeleteInfo()
this.showToast(`deleted ${this.deleteInfo.name}`, {
position: 'bottom-right',
})
}
const tmpCurrentPage = this.$refs.datatable_ref.currentPage
await this.refreshPage()
this.$refs.datatable_ref.currentPage = tmpCurrentPage
this.$refs.datatable_ref.inputPage(tmpCurrentPage)
},
download: async function (info) {
this.$emit('download', info)
downloadCsv: async function (meta) {
const href = location.href.split('/')[2]
if (meta.device.library_name.indexOf('Elite') >= 0) {
window.open('http://' + href + '/#/admin/download/elite/csv/' + meta.id, '_blank', 'width=500,height=100,left=200,top=200')
} else if (meta.device.library_name.indexOf('Neulive') >= 0) {
window.open('http://' + href + '/#/admin/download/neulive/csv/' + meta.id, '_blank', 'width=500,height=100,left=200,top=200')
}
},
downloadExcel: async function (meta) {
const href = location.href.split('/')[2]
if (meta.device.library_name.indexOf('Elite') >= 0) {
window.open('http://' + href + '/#/admin/download/elite/excel/' + meta.id, '_blank', 'width=500,height=100,left=200,top=200')
} else if (meta.device.library_name.indexOf('Neulive') >= 0) {
window.open('http://' + href + '/#/admin/download/neulive/csv/' + meta.id + '/true', '_blank', 'width=500,height=100,left=200,top=200')
}
},
replay: function (meta) {
if (meta.device.library_name.includes('Neulive') === true) {
// window.open('http://' + location.href.split('/')[2].split(':')[0] + '/#/admin/data-replay/neulive/' + meta.id)
// window.open('http://' + location.href.split('/')[2].split(':')[0] + '/#/admin/data-replay/' + meta.id)
this.$router.push({
path: '/admin/data-replay/neulive/' + meta.id,
path: '/admin/data-replay/' + meta.id,
})
} else if (meta.device.library_name.includes('Elite') === true) {
// window.open('http://' + location.href.split('/')[2].split(':')[0] + '/#/admin/data-replay/elite/' + meta.id)
+1 -1
View File
@@ -50,7 +50,7 @@ export default {
async initAll () {
await this.initTask({ id: getUniqueID(), desc: 'task description', instructions: getDefaultInstruction() })
await this.initDevice({ availableDevice: ['4'], deviceInfo: { 4: { battery: 0, device_name: '', device_address: [], device_version: '', library_name: '', library_version: '', serial_number: [], status: '', isSync: false, isStimulatemulate: false, parent: '' } } })
await this.initDevice({ availableDevice: ['4'], deviceInfo: { 4: { battery: 0, device_name: '', device_address: [], device_version: '', library_name: '', library_version: '', serial_number: [], status: '', isSync: false, isStimulate: false, parent: '' } } })
await this.initParam({ id: getUniqueID(), paramsSet: { alias: 'default', desc: '', recording: { ADC_CLOCK: 200, AMP_GAIN: 0, RECORDING_CH: 0 } } })
},
async AddTask () {
+75 -9
View File
@@ -99,6 +99,7 @@ import { chartData } from '../../../data/task/ChartsManagement'
import { taskInfo } from '../../../data/task/TaskInfo'
import CanvasChart from './chart/CanvasChart'
import TaskDevices from './controller/TaskDevices'
// import api from '../../../data/api'
// import TaskFormula from './formula/TaskFormula'
// TODO change chart data tag format
@@ -110,9 +111,9 @@ export default {
TaskDevices,
// TaskFormula,
},
async created () {
await taskInfo.updateTaskInfo(this.$route.params.taskID)
},
// async created () {
// await taskInfo.updateTaskInfo(this.$route.params.taskID)
// },
data () {
return {
// modal
@@ -128,6 +129,8 @@ export default {
selectChartID: null,
showDeviceSetting: true,
chartAreaClass: ['flex', 'xs12', 'sm12', 'md12', 'xl8', 'pa-0'],
deviceList: {},
}
},
mqtt: {
@@ -149,6 +152,47 @@ export default {
},
async '+/hardware_device/+' (data, topic) {
await taskInfo.deviceInfo(String.fromCharCode.apply(null, data))
console.log(this.deviceList)
for (const d1 in taskInfo.getTaskInfo().deviceList) {
if (taskInfo.getTaskInfo().deviceList[d1].info.device_address.length > 0) {
const addr1 = taskInfo.getTaskInfo().deviceList[d1].info.device_address.join()
let parameter, content
for (const d2 in this.deviceList) {
const addr2 = this.deviceList[d2].info.device_address.join()
if (addr1 === addr2) {
console.log(this.deviceList[d2].parameterSet)
for (const p in this.deviceList[d2].parameterSet) {
if (p !== 'STIMULATING') {
if (parameter == null) {
parameter = p
} else {
parameter = parameter + '|' + p
}
let c
if (Array.isArray(this.deviceList[d2].parameterSet[p])) {
c = '0:' + this.deviceList[d2].parameterSet[p].length + '=' + this.deviceList[d2].parameterSet[p]
} else {
c = this.deviceList[d2].parameterSet[p]
}
if (content == null) {
content = c
} else {
content = content + '|' + c
}
}
}
console.log('****', parameter, content)
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_parameter/0',
device: parseInt(d1),
parameter: parameter,
content: content,
}))
}
}
}
}
if (this.$refs.devices_ref != null) {
await this.$refs.devices_ref.loadingDone()
}
@@ -157,8 +201,9 @@ export default {
async '+/data_server/device_data_stream/+/+' (data, topic) {
const topicSplit = topic.split('/')
if (!taskInfo.getDeviceInfoByRawID(parseInt(topicSplit[3])).info.isSync) {
taskInfo.deviceStart(parseInt(topicSplit[3]))
chartData.defaultChartGenerator(taskInfo.getDeviceIDByRaw(parseInt(topicSplit[3])), null, 'device')
if (chartData.defaultChartGenerator(taskInfo.getDeviceIDByRaw(parseInt(topicSplit[3])), null, 'device')) {
taskInfo.deviceStart(parseInt(topicSplit[3]))
}
}
dataStreamBuffer.into(String.fromCharCode.apply(null, data), parseInt(topicSplit[3]), (parseInt(topicSplit[4]) + 1))
},
@@ -256,6 +301,14 @@ export default {
if (await this.$refs.devices_ref != null) {
await this.$refs.devices_ref.loadingStart()
}
// let _parameter, _content
// this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
// header: 'device_parameter/0',
// device: 7,
// parameter: 'RECORDING_CH|AXIS_CH',
// content: '7|1',
// }))
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'hardware_device/0',
}))
@@ -279,9 +332,13 @@ export default {
}
},
refreshDevicesWindow: function () {
// console.log(taskInfo.getTaskInfo())
if (this.$refs.devices_ref != null) {
this.$refs.devices_ref.refresh()
}
// api.task.update({
// device_config: taskInfo.getTaskInfo().deviceList,
// })
},
addChart: async function () {
const defaultID = {}
@@ -377,8 +434,7 @@ export default {
this.chartAreaClass[3] = 'md12'
this.chartAreaClass[4] = 'xl12'
},
addDevice: async function (deviceID) {
this.mqttSub(taskInfo.getTaskInfo().controllerID + '/data_server/device_data_stream/' + taskInfo.getRawDeviceID(deviceID) + '/+')
addMappingChart: async function (deviceID) {
const chart = await this.addChart()
await this.$nextTick(async () => {
chartData.getAllChartsData()[chart].mappingID = deviceID
@@ -388,9 +444,19 @@ export default {
})
}
})
return chart
},
addDevice: async function (deviceID) {
this.mqttSub(taskInfo.getTaskInfo().controllerID + '/data_server/device_data_stream/' + taskInfo.getRawDeviceID(deviceID) + '/+')
const chart = this.addMappingChart(deviceID)
if (taskInfo.getDeviceInfo(deviceID).info.isSync) {
chartData.defaultChartGenerator(deviceID, chart, 'device')
}
// console.log(chartData.getAllChartsData())
// console.log(taskInfo.getTaskInfo())
// await api.task.update({
// device_config: taskInfo.getTaskInfo().deviceList,
// })
this.pageToast('The device [' + deviceID + '] has been registered.')
},
removeDevice: function (deviceID) {
@@ -497,11 +563,11 @@ export default {
watch: {
},
async mounted () {
// await taskInfo.updateTaskInfo(this.$route.params.taskID)
this.deviceList = await taskInfo.updateTaskInfo(this.$route.params.taskID)
console.log(taskInfo.getTaskInfo())
// this.screenHeight = document.documentElement.clientHeight
this.pageMqttSub(taskInfo.getTaskInfo().controllerID)
console.log(taskInfo.getTaskInfo().controllerID)
await this.pageInit()
// this.chartNumber = taskInfo.getTaskInfo().chartNumber
@@ -30,23 +30,62 @@
<div v-else :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" >
<canvas-chart-setting></canvas-chart-setting>
</div>
<div class="flex row xs12 md12 xl12 sm12" style="text-align: center;" >
<div>
<va-select
class="xs6 md6 xl6 sm6"
<div class="flex row">
<div class="flex row xs12 md12 xl12 sm12" style="text-align: center;" >
<!-- <va-select
class="ma-1"
:on-change="mappingSelectChange()"
small
:label="'MAPPING'"
v-model="mappingSelect"
textBy="name"
:options="mappingOptions"
/>
</div>
<div>
<va-button small @click="init()">INIT</va-button>
/> -->
<va-input
v-if="data.chartXMode === 'time'"
class="ma-1"
@keyup.enter="timeIntervalChange(timeIntervalInput)"
@blur="timeIntervalChange(timeIntervalInput)"
v-model="timeIntervalInput"
:label="'time-interval'"
>
<p slot="append" style="margin-right: 0;" small>
ms
</p>
</va-input>
<va-input
v-if="data.chartXMode === 'value'"
class="ma-1"
@keyup.enter="xIntervalChange(xIntervalInput)"
@blur="xIntervalChange(xIntervalInput)"
v-model="xIntervalInput"
:label="'x-interval'"
>
</va-input>
<va-input
class="ma-1"
@keyup.enter="yIntervalChange(yIntervalInput)"
@blur="yIntervalChange(yIntervalInput)"
v-model="yIntervalInput"
:label="'y-interval'"
>
</va-input>
<va-input
v-if="data.chartDevice === 'neulive'"
class="ma-1"
@keyup.enter="threeAxisIntervalChange(threeAxisIntervalInput)"
@blur="threeAxisIntervalChange(threeAxisIntervalInput)"
v-model="threeAxisIntervalInput"
:label="'3axis-interval'"
>
</va-input>
<va-button class="no-dark-style-va-button" small @click="init()">INIT</va-button>
<va-button small color="dark" @click="remove()">REMOVE</va-button>
</div>
<!-- <div class="xs2 md2 xl2 sm2" style="text-align: center;" >
<va-button class="no-dark-style-va-button" small @click="init()">INIT</va-button>
<va-button small color="dark" @click="remove()">REMOVE</va-button>
</div> -->
</div>
</va-card>
</div>
@@ -98,6 +137,10 @@ export default {
mappingOptions: taskInfo.getMappingList(),
nameCard: chartData.getAllChartsData()[this.chartID].cardName,
initDone: false,
timeIntervalInput: '',
threeAxisIntervalInput: '',
xIntervalInput: '',
yIntervalInput: '',
}
},
computed: {
@@ -105,6 +148,34 @@ export default {
watch: {
},
methods: {
timeIntervalChange: function (val) {
chartData.getAllChartsData()[this.chartID].xAxis.forEach(x => {
if (x.type === 'time') {
x.interval = val * 1000
}
})
},
xIntervalChange: function (val) {
chartData.getAllChartsData()[this.chartID].xAxis.forEach(x => {
if (x.type === 'value') {
x.interval = val * 1
}
})
},
yIntervalChange: function (val) {
chartData.getAllChartsData()[this.chartID].yAxis.forEach(y => {
if (parseInt(y.channel) <= 255) {
y.interval = val * 1
}
})
},
threeAxisIntervalChange: function (val) {
chartData.getAllChartsData()[this.chartID].yAxis.forEach(y => {
if (parseInt(y.channel) >= 255) {
y.interval = val * 1
}
})
},
init: function () {
this.mappingSelect = ''
this.nameCard = 'chart' + this.chartID
@@ -169,3 +240,11 @@ export default {
}
</script>
<style lang="scss">
.no-dark-style-va-button {
&:focus {
filter: brightness(100%);
}
}
</style>
@@ -44,12 +44,14 @@
<va-item class="pa-0 ma-0 mt-2">
<va-item-section class="ml-3">
<va-item-label>
<va-button @click.stop="start(device)" v-if="!device.isSync" class="px-2 py-0 mr-0" color="success" small>START</va-button>
<va-button @click.stop="stop(device)" v-if="device.isSync" :disabled="device.stopping" class="px-2 py-0 mr-0" color="danger" small>STOP</va-button>
<va-button @click.stop="detect(device)" v-if="device.type == 'Elite'" color="primary" class="px-2 py-0 mr-0" small>DETECT</va-button>
<va-button @click.stop="stimulate(device)" v-if="device.type == 'Neulive' && !device.isStimulate" color="warning" class="px-2 py-0 mr-0" small>STIMULATE</va-button>
<va-button @click.stop="stopStimulate(device)" v-if="device.type == 'Neulive' && device.isStimulate" color="danger" class="px-2 py-0 mr-0" small>STOP</va-button>
<va-button @click.stop="fastSettle(device)" v-if="device.type == 'Neulive'" color="info" class="px-2 py-0 mr-0" small>R</va-button>
<va-button @click.stop="start(device)" v-if="(device.type == 'Neulive' && !device.isSync && !device.isStimulate) || (device.type == 'Elite' && !device.isSync)" class="px-2 py-0 mr-0" color="success" small>START</va-button>
<va-button @click.stop="stop(device)" v-if="(device.type == 'Neulive' && (device.isSync || device.isStimulate)) || (device.type == 'Elite' && device.isSync)" :disabled="device.stopping" class="px-2 py-0 mr-0" color="danger" small>STOP</va-button>
<va-button id="detectButton" @click.stop="detect(device)" v-if="device.type == 'Elite'" color="primary" class="px-2 py-0 mr-0" small>DETECT</va-button>
<va-button @click.stop="record(device)" v-if="device.type == 'Neulive' && !device.isSync" color="primary" class="px-2 py-0 mr-0 no-dark-style-va-button" small>RECORD</va-button>
<va-button @click.stop="stopRecord(device)" v-if="device.type == 'Neulive' && device.isSync" color="danger" class="px-2 py-0 mr-0 no-dark-style-va-button" small>STOP REC</va-button>
<va-button @click.stop="stimulate(device)" v-if="device.type == 'Neulive' && !device.isStimulate" color="warning" class="px-2 py-0 mr-0 no-dark-style-va-button" small>STIMULATE</va-button>
<va-button @click.stop="stopStimulate(device)" v-if="device.type == 'Neulive' && device.isStimulate" color="danger" class="px-2 py-0 mr-0" small>STOP STI</va-button>
<va-button @click.stop="fastSettle(device)" v-if="device.type == 'Neulive'" color="info" class="px-2 py-0 mr-0 no-dark-style-va-button" small>R</va-button>
</va-item-label>
</va-item-section>
</va-item>
@@ -57,7 +59,7 @@
<div slot="body">
<div class="mt-0 mb-0" style="height: 350px; overflow-y: scroll; overflow-x: hidden;" :key="'detail' + device.id">
<div style="text-align: center;">
<va-button @click.stop="generateChart(device)" class="pl-2 pr-2 mr-0" small>GENERATE MAPPING CHART</va-button>
<va-button @click.stop="generateChart(device)" class="pl-2 pr-2 mr-0 no-dark-style-va-button" small>GENERATE MAPPING CHART</va-button>
</div>
<div>
<file-control-window :ref="'fcwindow_ref'" :deviceID="device.id" class="pl-0 pr-0" />
@@ -116,22 +118,25 @@ export default {
// this.$emit('start', device)
setTimeout(() => {
this.$emit('start', device)
}, 100)
}, 500)
this.pageToast('The device ' + device.name + ' has been started.')
},
stop: function (device) {
this.$emit('stop', device)
this.pageToast('The device ' + device.name + ' has been stopped.')
},
record_start: function (device) {
this.setArchiveSettings()
this.$emit('record_start', device)
record: function (device) {
device.stopping = false
this.setArchiveSettings()
setTimeout(() => {
this.$emit('record', device)
}, 500)
this.pageToast('The device ' + device.name + ' has been started.')
},
record_stop: function (device) {
stopRecord: function (device) {
device.stopping = true
this.$emit('record_stop', device)
this.$emit('stopRecord', device)
this.pageToast('The device ' + device.name + ' has been stopped.')
},
generateChart: function (device) {
@@ -187,6 +192,17 @@ export default {
this.$emit('fast_settle', device)
this.pageToast('The device ' + device.name + ' fast settle.')
},
recoverDetectButton () {
document.getElementById('detectButton').className += ' no-dark-style-va-button'
},
},
}
</script>
<style lang="scss">
.no-dark-style-va-button {
&:focus {
filter: brightness(100%);
}
}
</style>
@@ -15,7 +15,19 @@
</div>
<div v-else class="flex row align--center">
<task-device-list :ref="'pdlist_ref'" :deviceList="deviceList" @remove="removeDevice($event)" @start="startDevice($event)" @stop="stopDevice($event)" @record_start="startRecord($event)" @record_stop="stopRecord($event)" @sti="sti($event)" @sti_stop="stiStop($event)" @fast_settle="fastSettle($event)" @generate="generateChart($event)" @detect="detectDevice($event)" />
<task-device-list
:ref="'pdlist_ref'"
:deviceList="deviceList"
@remove="removeDevice($event)"
@start="startDevice($event)"
@stop="stopDevice($event)"
@record="record($event)"
@stopRecord="stopRecord($event)"
@sti="sti($event)" @sti_stop="stiStop($event)"
@fast_settle="fastSettle($event)"
@generate="generateChart($event)"
@detect="detectDevice($event)"
/>
<div class="row flex xs12 md12 xl12 sm12 mt-2" style="text-align: center;">
<div class="xs10 md10 xl10 sm10">
@@ -44,6 +56,7 @@ import TaskDeviceList from './TaskDeviceList'
import { taskInfo } from '../../../../data/task/TaskInfo'
import { chartData } from '../../../../data/task/ChartsManagement'
import { dataStreamBuffer } from '../../../../data/task/DataStreamBuffer'
import api from '@/data/api'
export default {
name: 'TaskDevices',
@@ -85,14 +98,26 @@ export default {
},
loadingDone: async function () {
this.state.LOADING = false
// const ret = await api.task.getAll()
// if (ret.data.length > 0) {
// for (const device in ret.data[0].device_config) {
// if (ret.data[0].device_config[device].device_address) {
// }
// }
// }
this.clearDevice()
console.log(this.deviceOptions)
for (let i = this.deviceOptions.length - 1; i >= 0; i--) {
this.deviceSelect = this.deviceOptions[i]
await this.addDevice(this.deviceOptions[i].id)
// this.sleep(500).then(() => {
// this.addDevice(this.deviceOptions[i].id)
// })
for (let i = 4; i <= 7; i++) {
await this.addDevice(i)
}
// for (let i = this.deviceOptions.length - 1; i >= 0; i--) {
// this.deviceSelect = this.deviceOptions[i]
// await this.addDevice(this.deviceOptions[i].id)
// // this.sleep(500).then(() => {
// // this.addDevice(this.deviceOptions[i].id)
// // })
// }
},
startDevice: async function (device) {
await chartData.defaultChartGenerator(device.id, null, 'device')
@@ -103,8 +128,21 @@ export default {
device: taskInfo.getRawDeviceID(device.id),
instruction: 'record',
}))
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'stimulate',
}))
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_parameter/0',
device: taskInfo.getRawDeviceID(device.id),
parameter: 'STIMULATING',
content: 1,
}))
taskInfo.getTaskInfo().deviceList[(taskInfo.getRawDeviceID(device.id)).toString()].parameterSet.STIMULATING = 1
device.isStimulate = true
} else if (taskInfo.getDeviceInfo(device.id).info.library_name.startsWith('Elite')) {
console.log('elite')
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
@@ -115,6 +153,9 @@ export default {
device.isSync = true
this.$emit('refreshSetting')
// ### show device info
api.task.update({
device_config: taskInfo.getTaskInfo().deviceList,
})
console.log(taskInfo.getDeviceInfo(device.id))
}
},
@@ -127,6 +168,18 @@ export default {
device: taskInfo.getRawDeviceID(device.id),
instruction: 'stop_record',
}))
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'stop_stimulate',
}))
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_parameter/0',
device: taskInfo.getRawDeviceID(device.id),
parameter: 'STIMULATING',
content: 0,
}))
device.isStimulate = false
} else if (taskInfo.getDeviceInfo(device.id).info.library_name.startsWith('Elite')) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
@@ -149,13 +202,23 @@ export default {
device: taskInfo.getRawDeviceID(device.id),
instruction: 'VIS_DEVICE_DONE',
}))
this.$refs.pdlist_ref.recoverDetectButton()
}, 5000)
},
startRecord: async function (device) {
record: async function (device) {
await chartData.defaultChartGenerator(device.id, null, 'device')
if (!taskInfo.getDeviceInfo(device.id).info.isSync) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'record',
}))
device.isSync = true
device.stopping = false
this.$emit('refreshSetting')
api.task.update({
device_config: taskInfo.getTaskInfo().deviceList,
})
// ### show device info
console.log(taskInfo.getDeviceInfo(device.id))
@@ -164,13 +227,14 @@ export default {
stopRecord: function (device) {
dataStreamBuffer.removeByDevice(taskInfo.getRawDeviceID(device.id))
if (taskInfo.getDeviceInfo(device.id).info.isSync) {
// this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
// header: 'device_instruction/0',
// device: taskInfo.getRawDeviceID(device.id),
// instruction: 'interrupt',
// }))
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'stop_record',
}))
}
// device.isSync = false
device.isSync = false
device.stopping = true
},
sti: function (device) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
@@ -184,6 +248,11 @@ export default {
parameter: 'STIMULATING',
content: 1,
}))
taskInfo.getTaskInfo().deviceList[(taskInfo.getRawDeviceID(device.id)).toString()].parameterSet.STIMULATING = 1
api.task.update({
device_config: taskInfo.getTaskInfo().deviceList,
})
device.isStimulate = true
},
stiStop: function (device) {
@@ -242,7 +311,10 @@ export default {
if (selectID == null) {
return false
}
const addr = taskInfo.getDeviceInfoByRawID(selectID).info.device_address
if (addr.length === 0) {
return false
}
await taskInfo.getTaskInfo().deviceAddrList.push(taskInfo.getDeviceInfoByRawID(selectID).info.device_address)
await taskInfo.getTaskInfo().taskDeviceID.push(selectID)
const _address = this.GLOBAL.transMac(taskInfo.getDeviceInfoByRawID(selectID).info.device_address)
@@ -287,6 +359,12 @@ export default {
taskInfo.updateAllList()
this.$emit('remove', device.id)
},
clearDevice: async function () {
taskInfo.getTaskInfo().deviceAddrList.length = 0
taskInfo.getTaskInfo().taskDeviceID.length = 0
this.deviceList.length = 0
taskInfo.updateAllList()
},
generateChart: function (device) {
this.$emit('add', device.id)
},
@@ -76,26 +76,26 @@ export default {
fileNameChange: async function (name) {
if (this.enableSetting) {
if (this.deviceInfo.info.isSync === false) {
let fileNameCount = await api.getMetaFilesByName(name)
let fileNameCount = await api.meta.getByName(name)
if (fileNameCount.data != null) {
let duplicateCount = 1
let fileName = name
while (fileNameCount.data.length !== 0) {
const res = name.split('(')[0]
fileName = `${res}(${duplicateCount})`
fileNameCount = await api.getMetaFilesByName(fileName)
fileNameCount = await api.meta.getByName(fileName)
duplicateCount += 1
}
this.fileNameInput = fileName
}
if (name !== this.deviceInfo.info.recording_file_name) {
this.deviceInfo.info.recording_file_name = name
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_recording_file_name/0',
device: taskInfo.getRawDeviceID(this.deviceID),
content: name,
}))
if (fileName !== this.deviceInfo.info.recording_file_name) {
this.deviceInfo.info.recording_file_name = fileName
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_recording_file_name/0',
device: taskInfo.getRawDeviceID(this.deviceID),
content: fileName,
}))
}
}
}
}
@@ -143,7 +143,7 @@ export default {
this.fileNameChange(this.fileNameInput)
// directory init
const collection = await api.getCollectionsAll()
const collection = await api.collection.getAll()
this.directoryOptions = collection.data.filter(el => el.name !== 'root')
if (Object.keys(this.deviceInfo.info.parent).length === 0) {
@@ -178,7 +178,7 @@ export default {
},
mounted () {
this.pageInit()
this.enableTimer = setTimeout(this.enableChangeFile, 1500)
this.enableTimer = setTimeout(this.enableChangeFile, 1000)
},
destroyed () {
clearTimeout(this.enableTimer)
@@ -214,8 +214,8 @@
<div class="row">
<div class="flex sm12 xl12 md12 xs12">
<div class="flex row align--center">
<va-button slot="append" class="mr-2 pa-1 shrink" small @click="cycleNoNumberChange(0)">
0
<va-button slot="append" class="mr-2 pa-1 shrink" small @click="cycleNoNumberChange(1)">
1
</va-button>
<va-input
@keyup.enter="cycleNoNumberChange(cycleNoNumberInput)"
@@ -235,7 +235,7 @@
class="flex sm12 xl12 md12 xs12"
value-visible
v-model="cycleNoNumber"
:min="0"
:min="1"
:max="249"
/>
</div>
@@ -718,8 +718,8 @@
<div class="row">
<div class="flex sm12 xl12 md12 xs12">
<div class="flex row align--center">
<va-button slot="append" class="mr-2 pa-1 shrink" small @click="cycleNoNumberChange(0)">
0
<va-button slot="append" class="mr-2 pa-1 shrink" small @click="cycleNoNumberChange(1)">
1
</va-button>
<va-input
@keyup.enter="cycleNoNumberChange(cycleNoNumberInput)"
@@ -739,7 +739,7 @@
class="flex sm12 xl12 md12 xs12"
value-visible
v-model="cycleNoNumber"
:min="0"
:min="1"
:max="249"
/>
</div>
@@ -295,6 +295,11 @@ export default {
value: 80,
description: '10k',
},
{
id: 6,
value: 40,
description: '20k',
},
],
radioFrequencySelect: null,
radioFrequencyOptions: [
@@ -472,7 +477,7 @@ export default {
}
},
ampGainSelectChange () {
if (this.ampGainSelect != null && this.ampGainSelect.id !== ((taskInfo.getDeviceInfo(this.deviceID).parameterSet.AMP_GAIN + 1) % 4)) {
if (this.ampGainSelect != null && this.ampGainSelect.id !== ((taskInfo.getDeviceInfo(this.deviceID).parameterSet.AMP_GAIN) % 4)) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_parameter/0',
device: taskInfo.getRawDeviceID(this.deviceID),
@@ -28,6 +28,7 @@
<div class="mt-4">
<div class="row sm12 xl12 md12 xs12">
<p class="display-6">ELECTRODE</p>
<va-button flat color="gray" icon="fa fa-info-circle" style="margin: 0.001rem; padding: 0.001rem;" @click.stop="toggleModal('ELECTRODE')"/>
</div>
<div class="row">
<div class="flex sm12 xl12 md12 xs12">
@@ -174,6 +175,7 @@
<div class="mt-4">
<div class="row sm12 xl12 md12 xs12">
<p class="display-6">PATTERN</p>
<va-button flat color="gray" icon="fa fa-info-circle" style="margin: 0.001rem; padding: 0.001rem;" @click.stop="toggleModal('PATTERN')"/>
</div>
<div class="row">
<div class="flex sm12 xl12 md12 xs12">
@@ -183,7 +185,10 @@
outline
v-model="patternModeSelect"
:options="patternModeOptions"
/>
>
</va-button-toggle>
<img src='@/assets/img/Monophasic.png' v-if="patternModeSelect==0" class="sti_pattern_img">
<img src='@/assets/img/Biphasic.png' v-if="patternModeSelect==1" class="sti_pattern_img">
</div>
</div>
@@ -326,8 +331,22 @@
</div>
</div>
</div>
<va-modal
v-model="showGuideLineModal.ELECTRODE"
position="right"
cancelText=""
>
<img src='@/assets/img/sti_user_guide.png' class="sti_guideline">
</va-modal>
<va-modal
v-model="showGuideLineModal.PATTERN"
position="right"
cancelText=""
>
<img src='@/assets/img/sti_user_guide.png' class="sti_guideline">
</va-modal>
</div>
</template>
@@ -350,6 +369,7 @@ export default {
},
data () {
return {
showGuideLineModal: { ELECTRODE: false, PATTERN: false },
stimulationOn: false,
posChannelList: [2],
negChannelList: [1],
@@ -440,6 +460,13 @@ export default {
mqtt: {
},
methods: {
toggleModal (which) {
if (which === 'ELECTRODE') {
this.showGuideLineModal.ELECTRODE = true
} else if (which === 'PATTERN') {
this.showGuideLineModal.PATTERN = true
}
},
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
@@ -827,3 +854,21 @@ export default {
},
}
</script>
<style lang="scss">
.sti_guideline {
height: 75vh;
width: 65vw;
text-align: left;
justify-content: center;
position: relative;
}
.sti_pattern_img {
height: 22.5vh;
width: 17.5vw;
text-align: center;
justify-content: center;
position: relative;
}
</style>
@@ -6,6 +6,7 @@
{{ minValue }}
</va-button>
<va-input
@mouseleave.native="cycleNumberChange(cycleNoNumberInput)"
@keyup.enter="cycleNumberChange(cycleNoNumberInput)"
@blur="cycleNumberChange(cycleNoNumberInput)"
v-model="cycleNoNumberInput"
@@ -6,6 +6,7 @@
{{ minValue }}
</va-button>
<va-input
@mouseleave.native="currentNumberChange(currentNumberInput)"
@keyup.enter="currentNumberChange(currentNumberInput)"
@blur="currentNumberChange(currentNumberInput)"
v-model="currentNumberInput"
@@ -6,6 +6,7 @@
{{ minValue }}
</va-button>
<va-input
@mouseleave.native="stepVoltNumberChange(voltNumberInput)"
@keyup.enter="stepVoltNumberChange(voltNumberInput)"
@blur="stepVoltNumberChange(voltNumberInput)"
v-model="voltNumberInput"
@@ -6,6 +6,7 @@
{{ minValue }}
</va-button>
<va-input
@mouseleave.native="resolutionNumberChange(resolutionNumberInput)"
@keyup.enter="resolutionNumberChange(resolutionNumberInput)"
@blur="resolutionNumberChange(resolutionNumberInput)"
v-model="resolutionNumberInput"
@@ -6,6 +6,7 @@
{{ minValue }}
</va-button>
<va-input
@mouseleave.native="voltScanRateNumberChange(voltScanRateNumberInput)"
@keyup.enter="voltScanRateNumberChange(voltScanRateNumberInput)"
@blur="voltScanRateNumberChange(voltScanRateNumberInput)"
v-model="voltScanRateNumberInput"
@@ -6,6 +6,7 @@
{{ minValue }}
</va-button>
<va-input
@mouseleave.native="voltNumberChange(voltNumberInput)"
@keyup.enter="voltNumberChange(voltNumberInput)"
@blur="voltNumberChange(voltNumberInput)"
v-model="voltNumberInput"
+27
View File
@@ -0,0 +1,27 @@
import api from './index'
const _header = {}
function setHeader (header) {
_header.Authorization = 'Bearer ' + header
}
function getHeader () {
if (Object.keys(_header).length === 0) {
getJwtData()
}
return _header
}
async function getJwtData () {
const _jwt = await api.axios.get('/public/auth/get_cookie')
setHeader(_jwt.data)
}
const auth = {
getHeader,
getJwtData,
}
export default auth
+81
View File
@@ -0,0 +1,81 @@
import api from './index'
import auth from './auth'
async function create (attrs) {
const _header = auth.getHeader()
const _data = {
name: attrs.name,
parent: attrs.parent,
type: attrs.type,
size: attrs.size,
}
try {
return await api.axios.post('/api/collection/create', _data, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByID (id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/collection/get_by_id/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByName (name) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/collection/get_by_name/${name}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByParent (type, parent) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/collection/get_by_parent/${type}/${parent}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAll () {
const _header = auth.getHeader()
try {
return await api.axios.get('/api/collection/get/all', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByParentName (collectionType, parent, name) {
console.log(collectionType, parent, name)
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/collection/get_by_parent_name/${collectionType}/${parent}/${name}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const collection = {
create,
getByID,
getByName,
getByParent,
getByParentName,
getAll,
}
export default collection
+52
View File
@@ -0,0 +1,52 @@
import api from './index'
import auth from './auth'
async function create (_data) {
const _header = auth.getHeader()
try {
return await api.axios.post('/api/controller/create/', _data, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAll () {
const _header = auth.getHeader()
console.log(_header)
try {
return await api.axios.get('/api/controller/get/all', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByMac (mac) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/controller/get_by_mac/${mac}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function update (attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post('/api/controller/update', attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const controller = {
create,
getAll,
getByMac,
update,
}
export default controller
+73
View File
@@ -0,0 +1,73 @@
import api from './index'
import auth from './auth'
async function create (attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post('/api/device/create', attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function updateByID (id, attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post(`/api/device/update_by_id/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function del (id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/device/clear_deleted/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByID (id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/device/get_by_id/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByName (name) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/device/get_by_name/${name}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAll () {
const _header = auth.getHeader()
try {
return await api.axios.get('/api/device/get/all', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const device = {
create,
updateByID,
del,
getByID,
getByName,
getAll,
}
export default device
+17 -327
View File
@@ -1,336 +1,26 @@
import axios from 'axios'
import auth from './auth'
import collection from './collection'
import controller from './controller'
import task from './task'
import device from './device'
import meta from './meta'
import raw from './raw'
import mini from './mini'
// axios.defaults.baseURL = 'http://192.168.3.53:3000'
axios.defaults.baseURL = 'http://' + location.href.split('/')[2].split(':')[0] + ':3000'
const _header = {}
function setHeader (header) {
_header.Authorization = 'Bearer ' + header
}
function getHeader () {
return _header
}
async function getJwtData () {
const _jwt = await axios.get('/public/auth/get_cookie')
setHeader(_jwt.data)
}
async function createCollection (attrs) {
const _header = getHeader()
const _data = {
name: attrs.name,
parent: attrs.parent,
type: attrs.type,
size: attrs.size,
}
try {
return await axios.post('/api/collection/create', _data, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getCollectionsByID (id) {
const _header = getHeader()
try {
return await axios.get('/api/collection/get_by_id/' + id, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getCollectionsByName (name) {
const _header = getHeader()
try {
return await axios.get('/api/collection/get_by_name/' + name, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getCollectionsByParent (type, parent) {
const _header = getHeader()
try {
return await axios.get('/api/collection/get_by_parent/' + type + '/' + parent, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getCollectionsAll () {
const _header = getHeader()
try {
return await axios.get('/api/collection/get/all', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getCollectionsByParentName (collectionType, parent, name) {
console.log(collectionType, parent, name)
const _header = getHeader()
try {
return await axios.get('/api/collection/get_by_parent_name/' + collectionType + '/' + parent + '/' + name, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function createMetaFile () {
const _header = getHeader()
try {
return await axios.post('/api/file/meta/create', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function updateMetaFile (id, attrs) {
console.log('updateMetaFile')
const _header = getHeader()
try {
return await axios.post(`/api/file/meta/update/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function updateRawFile (channel, id, attrs) {
console.log('updateRawFile')
const _header = getHeader()
try {
return await axios.post(`/api/file/raw/update/${channel}/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function updateMiniFile (channel, id, attrs) {
console.log('updateMiniFile')
const _header = getHeader()
try {
return await axios.post(`/api/file/mini/update/${channel}/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function clearDeleteMetaFile (id) {
console.log('clearDeleteMetaFile')
const _header = getHeader()
try {
return await axios.get(`/api/file/meta/clear_deleted/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function clearDeleteRawFile (channel, id) {
console.log('clearDeleteRawFile')
const _header = getHeader()
try {
return await axios.get(`/api/file/raw/clear_deleted/${channel}/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function clearDeleteMiniFile (channel, id) {
console.log('clearDeleteMiniFile')
const _header = getHeader()
try {
return await axios.get(`/api/file/mini/clear_deleted/${channel}/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getFolderMetaFileByParent (type, parent) {
const _header = getHeader()
try {
return await axios.get('/api/file/meta/get_by_parent/' + type + '/' + parent, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getRawFilesByID (channel, id) {
const _header = getHeader()
try {
return await axios.get('/api/file/raw/get_by_id/' + channel + '/' + id, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getRawFilesByIDs (channel, id) {
const _header = getHeader()
try {
return await axios.get('/api/file/raw/get_by_ids/' + channel + '/' + id, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getRawFilesAttrByIDs (channel, id, attr) {
const _header = getHeader()
try {
return await axios.get('/api/file/raw/get_attr_by_ids/' + channel + '/' + id + '/' + attr, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMetaFilesByID (id) {
const _header = getHeader()
try {
return await axios.get('/api/file/meta/get_by_id/' + id, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMetaFilesByName (name) {
const _header = getHeader()
try {
return await axios.get('/api/file/meta/get_by_name/' + name, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getRawFilesByParent (channel, parent) {
const _header = getHeader()
try {
return await axios.get('/api/file/raw/get_by_parent/' + channel + '/' + parent, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getRawFilesAttrByParent (channel, parent, attr) {
const _header = getHeader()
try {
return await axios.get('/api/file/raw/get_attr_by_parent/' + channel + '/' + parent + '/' + attr, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMiniFilesByID (channel, id) {
const _header = getHeader()
try {
return await axios.get('/api/file/mini/get_by_id/' + channel + '/' + id, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMiniFilesByParent (channel, parent) {
const _header = getHeader()
try {
return await axios.get('/api/file/mini/get_by_parent/' + channel + '/' + parent, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMiniFilesAttrByParent (channel, parent, attr) {
const _header = getHeader()
try {
return await axios.get('/api/file/mini/get_attr_by_parent/' + channel + '/' + parent + '/' + attr, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMiniFilesAttrByID (channel, id, attr) {
const _header = getHeader()
try {
return await axios.get('/api/file/mini/get_attr_by_id/' + channel + '/' + id + '/' + attr, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMiniFilesMeanDataByID (channel, id) {
const _header = getHeader()
try {
return await axios.get('/api/file/mini/mean/get_by_id/' + channel + '/' + id, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMiniFilesRandomDataByID (channel, id) {
const _header = getHeader()
try {
return await axios.get('/api/file/mini/random/get_by_id/' + channel + '/' + id, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const api = {
getJwtData,
createCollection,
getCollectionsByID,
getCollectionsByName,
getCollectionsByParent,
getCollectionsByParentName,
getCollectionsAll,
createMetaFile,
updateMetaFile,
updateRawFile,
updateMiniFile,
clearDeleteMetaFile,
clearDeleteRawFile,
clearDeleteMiniFile,
getFolderMetaFileByParent,
getRawFilesByParent,
getRawFilesByID,
getRawFilesByIDs,
getRawFilesAttrByIDs,
getMiniFilesByID,
getMiniFilesByParent,
getMiniFilesMeanDataByID,
getMiniFilesRandomDataByID,
getMetaFilesByID,
getMetaFilesByName,
getRawFilesAttrByParent,
getMiniFilesAttrByID,
getMiniFilesAttrByParent,
axios,
auth,
collection,
controller,
task,
device,
meta,
raw,
mini,
}
export default api
+74
View File
@@ -0,0 +1,74 @@
import api from './index'
import auth from './auth'
async function create () {
const _header = auth.getHeader()
try {
return await api.axios.post('/api/file/meta/create', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function update (id, attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post(`/api/file/meta/update/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function clearDel (id) {
console.log('clearDelete')
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/meta/clear_deleted/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getCollectionByParent (type, parent) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/meta/get_by_parent/${type}/${parent}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByID (id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/meta/get_by_id/${id}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByName (name) {
const _header = auth.getHeader()
try {
return await api.axios.get('/api/file/meta/get_by_name/' + name, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const meta = {
create,
update,
clearDel,
getCollectionByParent,
getByID,
getByName,
}
export default meta
+95
View File
@@ -0,0 +1,95 @@
import api from './index'
import auth from './auth'
async function update (channel, id, attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post(`/api/file/mini/update/${channel}/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function clearDel (channel, id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/mini/clear_deleted/${channel}/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByID (channel, id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/mini/get_by_id/${channel}/${id}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByParent (channel, parent) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/mini/get_by_parent/${channel}/${parent}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAttrByParent (channel, parent, attr) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/mini/get_attr_by_parent/${channel}/${parent}/${attr}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAttrByID (channel, id, attr) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/mini/get_attr_by_id/${channel}/${id}/${attr}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getMeanDataByID (channel, id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/mini/mean/get_by_id/${channel}/${id}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getRandomDataByID (channel, id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/mini/random/get_by_id/${channel}/${id}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const mini = {
update,
clearDel,
getByID,
getByParent,
getAttrByParent,
getAttrByID,
getMeanDataByID,
getRandomDataByID,
}
export default mini
+84
View File
@@ -0,0 +1,84 @@
import api from './index'
import auth from './auth'
async function update (channel, id, attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post(`/api/file/raw/update/${channel}/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function clearDel (channel, id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/raw/clear_deleted/${channel}/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByID (channel, id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/raw/get_by_id/${channel}/${id}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByIDs (channel, ids) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/raw/get_by_ids/${channel}/${ids}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAttrByIDs (channel, ids, attr) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/raw/get_attr_by_ids/${channel}/${ids}/${attr}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByParent (channel, parent) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/raw/get_by_parent/${channel}/${parent}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAttrByParent (channel, parent, attr) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/file/raw/get_attr_by_parent/${channel}/${parent}/${attr}`, { responseType: 'json', headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const raw = {
update,
clearDel,
getByID,
getByIDs,
getAttrByIDs,
getByParent,
getAttrByParent,
}
export default raw
+52
View File
@@ -0,0 +1,52 @@
import api from './index'
import auth from './auth'
async function create (_data) {
const _header = auth.getHeader()
try {
return await api.axios.post('/api/task/create/', _data, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getAll () {
const _header = auth.getHeader()
console.log(_header)
try {
return await api.axios.get('/api/task/get/all', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function getByID (id) {
const _header = auth.getHeader()
try {
return await api.axios.get(`/api/task/get_by_id/${id}`, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function update (attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post('/api/task/update', attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const task = {
create,
getAll,
getByID,
update,
}
export default task
+48 -20
View File
@@ -1,7 +1,44 @@
import { inflateSync } from 'zlib'
import streamSaver from 'streamsaver'
// import { inflateSync } from 'zlib'
import api from '../api/index'
var fileStream, writer
var encode = TextEncoder.prototype.encode.bind(new TextEncoder())
export const download = {
writeDataIntoFileStream: function (data, close) {
// const uInt8 = new TextEncoder().encode('StreamSaver is awesome')
// console.log(uInt8)
// console.log(uInt8.byteLength)
// writer.write(uInt8)
// streamSaver.createWriteStream() returns a writable byte stream
// The WritableStream only accepts Uint8Array chunks
// (no other typed arrays, arrayBuffers or strings are allowed)
// using Response can be a great tool to convert
// mostly anything (blob, string, buffers) into a byte stream
// that can be piped to StreamSaver
//
// You could also use a transform stream that would sit
// between and convert everything to Uint8Arrays
if (!fileStream) {
fileStream = streamSaver.createWriteStream('sample.csv')
writer = fileStream.getWriter()
}
data = encode(data)
data && writer.write(data)
// fileStream.locked = false
// new Response(data).body
// .pipeTo(fileStream, { preventClose: !close })
// .then()
},
closeWriter: function () {
writer.close()
},
getAllRawDatas: async function (meta) {
const result = {}
for (const channelID in meta.raw_data) {
@@ -11,10 +48,10 @@ export const download = {
while (rawDataIDList.length >= 1000) {
const _rawDataIDList = rawDataIDList.splice(0, 1000)
const _data = await api.getRawFilesAttrByIDs(channelID, _rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data')
const _data = await api.raw.getAttrByIDs(channelID, _rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data')
prevLastTime = await this.parseRawData(_data.data, prevLastTime, meta, result[channelID])
}
const _data = await api.getRawFilesAttrByIDs(channelID, rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data')
const _data = await api.raw.getAttrByIDs(channelID, rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data')
prevLastTime = await this.parseRawData(_data.data, prevLastTime, meta, result[channelID])
}
return result
@@ -25,38 +62,31 @@ export const download = {
result[channelID] = []
const prevLastTime = 0
const _data = await api.getRawFilesAttrByIDs(channelID, list, 'id-channel-size-serial_number-start_time-end_time-data')
const _data = await api.raw.getAttrByIDs(channelID, list, 'id-channel-size-serial_number-start_time-end_time-data')
await this.parseRawData(_data.data, prevLastTime, meta, result[channelID])
return result
},
rawByIDChannels: async function (id, channel, meta) {
const data = []
const rawData = await api.getRawFilesByID(channel, id)
const rawData = await api.raw.getByID(channel, id)
await this.parseRawData(rawData.data, null, meta, data)
return data
},
miniMeanByIDChannel: async function (id, channel, meta) {
const miniData = await api.getMiniFilesByID(channel, id)
const miniData = await api.mini.getByID(channel, id)
return await this.parseMiniData(miniData, 'data_mean', meta)
},
miniRandomByIDChannel: async function (id, channel, meta) {
const rawData = await api.getMiniFilesByID(channel, id)
const rawData = await api.mini.getByID(channel, id)
return await this.parseMiniData(rawData, 'data_random', meta)
},
parseRawData: async function (rawData, prevLastTime, meta, dataArray) {
for (const raw of rawData) {
if (raw.data !== null && raw.data.length > 0) {
const encodedData = raw.data.split('"***"')
const unzipDatas = []
for (const data of encodedData) {
if (data.length !== 0) {
const decodedData = atob(data)
const decodedDataBuffer = Buffer.from(decodedData, 'ascii')
const inflateData = inflateSync(decodedDataBuffer)
const _inflateData = new TextDecoder('utf-8').decode(inflateData).split(' ')
unzipDatas.push(_inflateData)
}
}
const unzipDatas = encodedData.map(ctx => {
return ctx.split(' ')
})
for (let i = 0; i <= unzipDatas.length - 1; i++) {
if (unzipDatas[i].length > 0) {
@@ -79,9 +109,7 @@ export const download = {
if (ctx.length === 0) {
return ''
}
const decodedData = atob(ctx)
const decodedDataBuffer = Buffer.from(decodedData, 'ascii')
return inflateSync(decodedDataBuffer).toString().split(' ')
return ctx.split(' ')
})
// console.log('unzipData', unzipDatas)
+75
View File
@@ -219,4 +219,79 @@ export const exportData = {
titlesString = ''
datasString = ''
},
createDatasString_1: function * (headers, data, cycle) {
// let dataString = ''
// let idx = 0
// const maxLength = 0
for (let j = 0; j < 10; j++) {
let dataString = ''
for (let idx = 0; idx < 100000; idx++) {
// console.log('idx', idx)
const indexData = []
// for (const i in range(cycle)) {
// for (const _ch of JSON.parse(headers.channels)) {
// // console.log('data', data[_ch][i][idx])
// if (data[_ch][i][idx + j * 1e5] === undefined) {
// indexData.push(...[])
// } else {
// indexData.push(...data[_ch][i][idx + j * 1e5])
// }
// }
// // idx = idx + 1
// }
dataString = dataString + indexData.join(',') + '\r\n'
}
// console.log('dataString', dataString)
yield dataString
}
console.log('done')
// if (JSON.parse(headers.channels).length > 0) {
// for (const channel of JSON.parse(headers.channels)) {
// if (data[channel].length > maxLength) {
// maxLength = data[channel].length
// }
// }
// for (const channel of JSON.parse(headers.channels)) {
// if (maxLength > data[channel].length) {
// let lengthDiff = maxLength - data[channel].length
// while (lengthDiff !== 0) {
// data[channel].push(['', ''])
// lengthDiff -= 1
// }
// }
// }
// const stopIndex = maxLength
// cycle = parseInt(stopIndex / 1e6)
// if (cycle === 0) {
// while (stopIndex !== idx) {
// const indexData = []
// for (const _ch of JSON.parse(headers.channels)) {
// indexData.push(...data[_ch][idx])
// }
// idx = idx + 1
// dataString = dataString + indexData.join(',') + '\r\n'
// }
// } else {
// for (let i = 0; i < 1e6; i++) {
// const indexData = []
// for (let j = 0; j <= cycle; j++) {
// for (const _ch of JSON.parse(headers.channels)) {
// if (data[_ch][idx + (j * 1e6)] === undefined) {
// indexData.push(...[])
// } else {
// indexData.push(...data[_ch][idx + (j * 1e6)])
// }
// }
// }
// idx = idx + 1
// dataString = dataString + indexData.join(',') + '\r\n'
// }
// }
// return [dataString, cycle]
// }
// return ''
},
}
+1 -1
View File
@@ -135,7 +135,7 @@ export const file = {
// pushDownloadInfo: function (path, downloadInfo) {
// _fileInfoList.find(fileInfo => fileInfo.data.path === path).data.meta.downloadBlockList.push(downloadInfo)
// },
// pushDownloadData: function (path, subfile, downldoadData) {
// pushdownloadBuffer: function (path, subfile, downldoadData) {
// const downloadInfo = _fileInfoList
// .find(fileInfo => fileInfo.data.path === path).data.meta.downloadBlockList
// .find(downloadInfo => downloadInfo.name === subfile)
+134 -40
View File
@@ -1,6 +1,7 @@
import newDataZoom from '@/factories/chart/dataZoomFactory'
import newChart, { newChartMode } from '@/factories/chart/chartFactory'
import newTooltip from '@/factories/chart/tooltipFactory'
// import newInterval from '@/factories/chart/intervalFactory'
import newSeries from '@/factories/chart/seriesFactory'
import { dataStreamBuffer } from './DataStreamBuffer'
import { taskInfo } from './TaskInfo'
@@ -22,33 +23,69 @@ function getIndexArrayForBalenceSampleRate (indexArray, dis, l) {
}
// generate x axis format
function makeXAxis (gridIndex, type) {
function makeXAxis (gridIndex, type, channel) {
return {
type: type,
name: '',
gridIndex: gridIndex,
axisLine: { onZero: false, lineStyle: { color: '#aaa' } },
axisTick: { show: false },
axisLabel: { show: true, showMinLabel: false, showMaxLabel: false, color: '#aaa' },
splitLine: { show: true, lineStyle: { color: '#eee' } },
axisLabel: {
show: true,
// interval: 2,
showMinLabel: false,
showMaxLabel: false,
color: '#aaa',
// rotate: 45,
margin: 12,
},
splitLine: { show: true, lineStyle: { color: '#aaa' } },
// minorSplitLine: {
// show: true,
// lineStyle: { color: '#eee' },
// },
// splitNumber: 20,
interval: 'auto',
scale: true,
min: null,
max: null,
min: 'dataMin',
max: 'dataMax',
channel: channel,
}
}
// generate y axis format
function makeYAxis (gridIndex, type) {
function makeYAxis (gridIndex, type, channel) {
return {
type: type,
// name: 'none',
// nameLocation: 'center',
// nameTextStyle: {
// // align: 'left',
// // verticalAlign: 'bottom',
// },
gridIndex: gridIndex,
axisTick: { show: false },
axisLine: { show: false }, // color: '#ccc' } },
axisLabel: { show: true, color: '#aaa', showMinLabel: false, showMaxLabel: false },
splitLine: { show: true, lineStyle: { color: '#eee' } },
axisLabel: {
show: true,
interval: 0,
color: '#aaa',
showMinLabel: false,
showMaxLabel: false,
},
splitLine: { show: true, lineStyle: { color: '#aaa' } },
// minorSplitLine: {
// show: true,
// lineStyle: { color: '#eee' },
// },
animation: false,
scale: true,
min: null,
max: null,
min: 'dataMin',
max: 'dataMax',
// splitNumber: 3,
// minInterval: 1,
interval: 'auto',
channel: channel,
}
}
@@ -60,7 +97,7 @@ function makeGrid (index, length) {
index: index,
top: _top,
height: _height,
left: '15%',
left: '10%',
right: '4%',
series: [],
}
@@ -428,37 +465,37 @@ export const chartData = {
// series.data.splice(0, series.data.length - _chartData[chartID].maxDots)
// }
if (series.data.length > 0) {
if (series.data[series.data.length - 1][0] - series.data[0][0] > 3000000) {
series.data.splice(0, popData.length)
}
}
// series data list shift by time
// if (series.data.length > 0) {
// if (series.xAxisSource[0] === -1) {
// if (taskInfo.getDeviceInfo(series.yAxisSource[0]).info.library_name.indexOf('Elite') >= 0) {
// if (series.data.length > _chartData[chartID].maxDots) {
// series.data.splice(0, series.data.length - _chartData[chartID].maxDots)
// }
// } else {
// if (series.data[series.data.length - 1][0] - series.data[0][0] > 3000000) {
// series.data.splice(0, popData.length)
// }
// }
// } else if (series.yAxisSource[0] === -1) {
// if (taskInfo.getDeviceInfo(series.xAxisSource[0]).info.library_name.indexOf('Elite') >= 0) {
// if (series.data.length > _chartData[chartID].maxDots) {
// series.data.splice(0, series.data.length - _chartData[chartID].maxDots)
// }
// } else {
// if (series.data[series.data.length - 1][1] - series.data[0][1] > 3000000) {
// series.data.splice(0, popData.length)
// }
// }
// if (series.data[series.data.length - 1][0] - series.data[0][0] > 3000000) {
// series.data.splice(0, popData.length)
// }
// }
// series data list shift by time
if (series.data.length > 0) {
if (series.xAxisSource[0] === -1) {
if (taskInfo.getDeviceInfo(series.yAxisSource[0]).info.library_name.indexOf('Elite') >= 0) {
if (series.data.length > _chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - _chartData[chartID].maxDots)
}
} else {
if (series.data[series.data.length - 1][0] - series.data[0][0] > 3000000) {
series.data.splice(0, popData.length)
}
}
} else if (series.yAxisSource[0] === -1) {
if (taskInfo.getDeviceInfo(series.xAxisSource[0]).info.library_name.indexOf('Elite') >= 0) {
if (series.data.length > _chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - _chartData[chartID].maxDots)
}
} else {
if (series.data[series.data.length - 1][1] - series.data[0][1] > 3000000) {
series.data.splice(0, popData.length)
}
}
}
}
// axis shift
if (series.data.length > 0) {
if (series.xAxisSource[0] === -1) {
@@ -653,6 +690,7 @@ export const chartData = {
const yType = setting[2]
const yValue = setting[3]
chartRegister(chartID, 0, xType, device.id, xValue, yType, device.id, yValue, null)
_chartData[chartID].chartDevice = 'elite'
} else if (taskInfo.getDeviceInfo(device.id).info.library_name.indexOf('Neulive') >= 0) {
const channelSet = taskInfo.getDeviceInfo(device.id).parameterSet.RECORDING_CH.toString(2).split('').reverse()
const axisChannelSet = taskInfo.getDeviceInfo(device.id).parameterSet.AXIS_CH.toString(2).split('').reverse()
@@ -692,6 +730,10 @@ export const chartData = {
}
}
})
for (let i = 0; i < _chartData[chartID].series.length - 1; i++) {
_chartData[chartID].xAxis[_chartData[chartID].series[i].xAxisIndex].axisLabel.show = false
}
_chartData[chartID].chartDevice = 'neulive'
}
}
@@ -718,8 +760,10 @@ export const chartData = {
}
} else {
// update all
let isSetting = false
for (const chartID in _chartData) {
if (parseInt(_chartData[chartID].mappingID) === parseInt(item.id)) {
isSetting = true
console.log(_chartData[chartID])
chartData.reset(chartID, _chartData[chartID].mappingID, _chartData[chartID].cardName)
console.log(_chartData[chartID])
@@ -734,7 +778,11 @@ export const chartData = {
}
}
}
if (isSetting === false) {
return false
}
}
return true
},
// get chart data by chart ID
@@ -836,14 +884,17 @@ const chartRegister = (chartID, gridIndex, deviceNameX, deviceIDX, channelX, dev
}
// create new axis
if (_xAxisIndex === -1) {
_chartData[chartID].xAxis.push(makeXAxis(gridIndex, xAxisType))
_chartData[chartID].xAxis.push(makeXAxis(gridIndex, xAxisType, channelX))
_xAxisIndex = _chartData[chartID].xAxis.length - 1
}
if (_yAxisIndex === -1) {
_chartData[chartID].yAxis.push(makeYAxis(gridIndex, yAxisType))
_chartData[chartID].yAxis.push(makeYAxis(gridIndex, yAxisType, channelY))
_yAxisIndex = _chartData[chartID].yAxis.length - 1
}
_chartData[chartID].chartXMode = _chartData[chartID].xAxis[_xAxisIndex].type
_chartData[chartID].chartYMode = _chartData[chartID].yAxis[_yAxisIndex].type
// update dataZoom AxisIndex list
const dataZoomXAxisIndex = Array.apply(null, { length: _chartData[chartID].xAxis.length }).map(Number.call, Number)
const dataZoomYAxisIndex = Array.apply(null, { length: _chartData[chartID].yAxis.length }).map(Number.call, Number)
@@ -882,6 +933,26 @@ const chartRegister = (chartID, gridIndex, deviceNameX, deviceIDX, channelX, dev
// const label = parseInt(parseInt(val / 1000000) / 60) + ' m ' + parseInt((val % 60000000) / 1000000) + ' s'
return label
}
} else if (sourceList[0].name === 'Elite') {
switch (sourceList[0].channel) {
case 1:
_chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + 'nA'
}
break
case 2:
_chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + 'uV'
}
break
case 3:
_chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + 'mΩ'
}
break
default:
break
}
}
// set yAxis format
@@ -909,6 +980,29 @@ const chartRegister = (chartID, gridIndex, deviceNameX, deviceIDX, channelX, dev
_chartData[chartID].yAxis[_yAxisIndex].min = -scaleRange
_chartData[chartID].yAxis[_yAxisIndex].max = scaleRange
}
_chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'uV'
}
} else if (sourceList[1].name === 'Elite') {
switch (sourceList[1].channel) {
case 1:
_chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'nA'
}
break
case 2:
_chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'uV'
}
break
case 3:
_chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'mΩ'
}
break
default:
break
}
}
// register series into grid
+18 -2
View File
@@ -1,5 +1,6 @@
import newTask from '@/factories/task/taskFactory'
import { dataStreamBuffer } from './DataStreamBuffer'
import api from '@/data/api'
const eliteImgUrl = require('@/assets/img/elite_img.png')
const neuliveImgUrl = require('@/assets/img/neulive_img.png')
@@ -81,13 +82,28 @@ const updateAllList = async () => {
export const taskInfo = {
updateTaskInfo: async (taskID) => {
let deviceList
const update = async () => {
_taskInfo.controllerID = 'tommy_test'
let contID = 0
const cont = await api.controller.getAll()
if (cont.data.length > 0) {
_taskInfo.controllerID = cont.data[0].mqtt_id
contID = cont.data[0].id
}
const task = await api.task.getAll()
if (task.data.length === 0) {
await api.task.create({
controller_id: contID,
})
} else {
deviceList = task.data[0].device_config
}
}
// _taskInfo.deviceAddrList = [[128, 111, 176, 237, 124, 140], [164, 218, 50, 212, 231, 58], [24, 4, 237, 55, 198, 53]]
// _taskInfo.chartNumber = _taskInfo.deviceAddrList.length
await update()
return _taskInfo
return deviceList
},
destroyed: () => {
+7
View File
@@ -1,6 +1,11 @@
function newChart (chartID) {
return {
chartID: parseInt(chartID),
chartType: 'detail',
chartDevice: 'neulive',
chartMode: 0,
chartXMode: 'value', // value or time
chartYMode: 'value', // value or time
cardName: 'chart' + String(chartID),
cardHeight: '500px',
cardWidth: 'auto',
@@ -38,6 +43,8 @@ function newChartMode (mode) {
settings[7] = ['Elite', 2, 'Elite', 1]
settings[8] = ['Elite', 2, 'Elite', 1]
settings[9] = ['Time', 2, 'Elite', 1]
settings[10] = ['Elite', 2, 'Elite', 1]
settings[11] = ['Time', 2, 'Elite', 1]
return settings[mode]
}
+5
View File
@@ -1,7 +1,10 @@
function newDataZoom () {
return [{
type: 'slider',
// height: '80%',
// top: '0%',
height: '10px',
// realtime: false,
bottom: '8%',
handleStyle: {
shadowColor: 'rgba(0, 0, 0, 0)',
@@ -12,9 +15,11 @@ function newDataZoom () {
}, {
type: 'inside',
xAxisIndex: [],
// realtime: false,
},
{
type: 'slider',
// realtime: false,
filterMode: 'none',
height: '85%',
showDataShadow: false,
+7
View File
@@ -36,6 +36,13 @@ function newSeries (type, legendName, xAxisIndex, yAxisIndex, xAxisSource, yAxis
lineStyle: {
width: 1.5,
},
markArea: {
data: [[{
xAxis: 0,
}, {
xAxis: 0,
}]],
},
data: [],
}
}
+32 -3
View File
@@ -1,3 +1,25 @@
function getTime (val) {
const hour = parseInt(val / 3.6e9)
const minute = parseInt((val % 3.6e9) / 1000000 / 60)
const second = parseInt((val % 6e7) / 1000000)
const millisecond = parseInt((val % 1e6) / 1000)
let label = ''
if (hour > 0) {
label += hour + ' h '
}
if (minute > 0) {
label += minute + ' m '
}
if (second > 0) {
label += second + ' s '
}
if (millisecond > 0) {
label += millisecond + ' ms '
}
// const label = parseInt(parseInt(val / 1000000) / 60) + ' m ' + parseInt((val % 60000000) / 1000000) + ' s'
return label
}
function newTooltip (chartID) {
return {
hideDelay: 5000,
@@ -7,14 +29,21 @@ function newTooltip (chartID) {
borderWidth: 1,
borderRadius: 0,
padding: 10,
// axisPointer: {
// type: 'cross',
// animation: false,
// label: {
// backgroundColor: '#505765',
// },
// },
formatter: function (params) {
if (params.length) {
if (params[0].seriesName.split('_')[0] === 'T' && params[0].seriesName.split('_')[1] !== 'T') {
params.unshift({ seriesName: 'Time', value: [null, parseFloat(params[0].value[0] / 1000000).toFixed(3) + ' s'], color: '#5193f2' })
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[0]))], color: '#5193f2' })
} else if (params[0].seriesName.split('_')[0] !== 'T' && params[0].seriesName.split('_')[1] === 'T') {
params.unshift({ seriesName: 'Time', value: [null, parseFloat(params[0].value[1] / 1000000).toFixed(3) + ' s'], color: '#5193f2' })
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[1]))], color: '#5193f2' })
} else {
params.unshift({ seriesName: 'Time', value: [null, parseFloat(params[0].value[2] / 1000000).toFixed(3) + ' s'], color: '#5193f2' })
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[2]))], color: '#5193f2' })
}
let tip = ''
for (var i = 0; i < params.length; i++) {
+12
View File
@@ -0,0 +1,12 @@
function newDownload () {
return {
_downloadIDList: [],
_downloadBuffer: [],
downloadIDList: {},
downloadBuffer: {},
progress: 0,
status: '',
}
}
export default newDownload
+13
View File
@@ -0,0 +1,13 @@
function newController (controllerID) {
return {
controller: {
name: '',
mac_address: '',
controller_id: '',
build_number: '',
update_time: '',
},
}
}
export default newController
+31
View File
@@ -0,0 +1,31 @@
function newDevice () {
return {
device: {
name: '',
mac_address: '',
serial_number: '',
configuration: '',
library: '',
library_version: '',
device_version: '',
battery: 0,
type: '',
temperature: '',
auto_connect: false,
connect_priorty: 0,
connect_time: 0,
status: '',
parameter_set: -1,
calibration: '',
user_auth: {
owner: [],
maintainer: [],
guest: [],
},
created_at: '',
updated_at: '',
},
}
}
export default newDevice
+42 -1
View File
@@ -81,6 +81,11 @@ export default new Router({
component: () => import('../components/dashboard/Dashboard.vue'),
default: true,
},
{
name: 'about',
path: 'about',
component: () => import('../components/about/aboutContent.vue'),
},
{
name: 'devices',
path: 'devices',
@@ -88,7 +93,7 @@ export default new Router({
},
{
name: 'neulive-data-replay',
path: 'data-replay/neulive/:metaList?',
path: 'data-replay/:metaList?',
component: () => import('../components/analysis/replay/neulive/NeuliveDataReplay.vue'),
},
{
@@ -114,6 +119,42 @@ export default new Router({
// keepAlive: true,
// },
},
// {
// name: 'download',
// path: 'download',
// component: () => import('../components/download/Download.vue'),
// // meta: {
// // keepAlive: true,
// // },
// },
{
name: 'neulive-csv-download',
path: 'download/neulive/csv/:metaList?/:recover?',
component: () => import('../components/download/neulive/csv/NeuliveDownloadCsv.vue'),
},
{
name: 'neulive-excel-download',
path: 'download/neulive/excel/:metaList?',
component: () => import('../components/download/neulive/excel/NeuliveDownloadExcel.vue'),
},
{
name: 'elite-csv-download',
path: 'download/elite/csv/:metaList?/:recover?',
component: () => import('../components/download/elite/csv/EliteDownloadCsv.vue'),
},
{
name: 'elite-excel-download',
path: 'download/elite/excel/:metaList?',
component: () => import('../components/download/elite/excel/EliteDownloadExcel.vue'),
},
{
name: 'settings',
path: 'settings',
component: () => import('../components/about/aboutContent.vue'),
// meta: {
// keepAlive: true,
// },
},
{
name: 'statistics',
path: 'statistics',
+14 -4
View File
@@ -3,9 +3,15 @@ import Vuex from 'vuex'
import VuexI18n from 'vuex-i18n' // load vuex i18n module
// import app from './modules/app'
import state from './state'
import neuliveReplay from './modules/analysis/replay/neulive'
import eliteReplay from './modules/analysis/replay/elite'
import replay from './modules/analysis/replay'
import projectContent from './modules/project/content'
import neuliveCsv from './modules/file/neulive/csv'
import neuliveExcel from './modules/file/neulive/excel'
import eliteCsv from './modules/file/elite/csv'
import eliteExcel from './modules/file/elite/excel'
// import eliteFile from './modules/file/elite'
// import file from './modules/file'
import about from './modules/about'
import mutations from './mutations'
import * as getters from './getters'
@@ -16,9 +22,13 @@ const store = new Vuex.Store({
strict: false, // process.env.NODE_ENV !== 'production',
getters,
modules: {
neuliveReplay,
eliteReplay,
replay,
neuliveCsv,
neuliveExcel,
eliteCsv,
eliteExcel,
projectContent,
about,
},
state: state,
mutations: mutations,
@@ -0,0 +1,17 @@
import types from '@/store/modules/about/types'
const typePath = types.controller
const controllerActs = {
/**
* init controller list
*
* @return {object} : controller data
*/
[typePath.init]: async ({ state, getters, commit, dispatch }, payload) => {
const controllers = await payload.api.controller.getAll()
commit(typePath.set, { list: controllers.data })
},
}
export default controllerActs
@@ -0,0 +1,66 @@
import types from '@/store/modules/about/types'
const typePath = types.device
const deviceActs = {
/**
* init devices list
*
* @param {object} api
*/
[typePath.init]: async ({ state, getters, commit, dispatch }, payload) => {
const devices = await payload.api.device.getAll()
commit(typePath.set, { deviceList: devices.data })
},
/**
* reorder devices list
*
* @param {object} api
* @param {object} deviceList
*/
[typePath.reorder]: async ({ state, getters, commit, dispatch }, payload) => {
if (payload.deviceList.length > 0) {
// update connect_priority according to id
payload.deviceList.map((v, idx) => {
v.connect_priority = idx
})
// update database device's info
for (const device of payload.deviceList) {
dispatch(typePath.updateDatabaseByID, { id: device.id, request: { connect_priority: device.connect_priority }, api: payload.api })
}
commit(typePath.set, { deviceList: payload.deviceList })
}
},
/**
* update database device table data by ID with request
*
* @param {number} id
* @param {object} request
* @param {object} api
*/
[typePath.updateDatabaseByID]: async ({ state, getters, commit, dispatch }, payload) => {
await payload.api.device.updateByID(payload.id, payload.request)
},
/**
* delete device
*
* @param {number} id
* @param {number} index
* @param {Array} deviceList
* @param {object} api
*/
[typePath.remove]: async ({ state, getters, commit, dispatch }, payload) => {
if (payload.deviceList.length > 0) {
payload.deviceList.splice(payload.index, 1)
dispatch(typePath.reorder, { deviceList: payload.deviceList, api: payload.api })
await dispatch(typePath.updateDatabaseByID, { id: payload.id, request: { deleted: true }, api: payload.api })
await payload.api.device.del(payload.id)
}
},
}
export default deviceActs
+7
View File
@@ -0,0 +1,7 @@
import deviceAct from './deviceAct'
import controllerAct from './controllerAct'
export default {
...deviceAct,
...controllerAct,
}
@@ -0,0 +1,44 @@
import types from '@/store/modules/about/types'
const typePath = types.controller
const controllerGets = {
/**
* get controller by list index
*
* @param {int} index
* @return {object} : controller info
*/
[typePath.getByIndex]: (state) => (index) => {
if (index == null || state.controllerInfoList[index] == null) {
return null
}
return state.controllerInfoList[index]
},
/**
* get controller by id
*
* @param {int} id
* @return {object} : controller info
*/
[typePath.getByID]: (state) => (id) => {
state.controllerInfoList.forEach(controller => {
if (controller.id === id) {
return controller
}
})
return null
},
/**
* get all controller info
*
* @return {Array} : controller list
*/
[typePath.getAll]: (state) => {
return state.controllerInfoList
},
}
export default controllerGets
@@ -0,0 +1,44 @@
import types from '@/store/modules/about/types'
const typePath = types.device
const deviceGets = {
/**
* get device by list index
*
* @param {int} index
* @return {object} : device info
*/
[typePath.getByIndex]: (state) => (index) => {
if (index == null || state.deviceInfoList[index] == null) {
return null
}
return state.deviceInfoList[index]
},
/**
* get device by id
*
* @param {int} id
* @return {object} : device info
*/
[typePath.getByID]: (state) => (id) => {
state.deviceInfoList.forEach(device => {
if (device.id === id) {
return device
}
})
return null
},
/**
* get all device info
*
* @return {Array} : device list
*/
[typePath.getAll]: (state) => {
return state.deviceInfoList
},
}
export default deviceGets
+7
View File
@@ -0,0 +1,7 @@
import deviceGet from './deviceGet'
import controllerGet from './controllerGet'
export default {
...deviceGet,
...controllerGet,
}
@@ -0,0 +1,30 @@
import types from '@/store/modules/about/types'
const typePath = types.controller
const controllerMutations = {
/**
* set controller info list
*
*/
[typePath.set]: async (state, payload) => {
state.controllerInfoList.length = 0
state.controllerInfoList.push(...payload.list)
},
/**
* update controller info list by index
*
* @param {number} index
* @param {any} item
*/
[typePath.updateByIndex]: async (state, payload) => {
for (const item in payload) {
if (item !== 'index') {
state.controllerInfoList[payload.index][item] = payload[item]
}
}
},
}
export default controllerMutations
@@ -0,0 +1,35 @@
import types from '@/store/modules/about/types'
const typePath = types.device
const deviceMutations = {
/**
* set device info list
*
* @param {Array} deviceList
*/
[typePath.set]: async (state, payload) => {
state.deviceInfoList.length = 0
state.deviceInfoList.push(...payload.deviceList)
},
/**
* update device info list by index
*
* @param {number} index
* @param {object} item
*/
[typePath.updateByIndex]: async (state, payload) => {
for (const idx in payload.item) {
state.deviceInfoList[payload.index][idx] = payload.item[idx]
}
},
[typePath.removeByIndex]: async (state, payload) => {
for (const idx in payload.item) {
state.deviceInfoList[payload.index][idx] = payload.item[idx]
}
},
}
export default deviceMutations
@@ -0,0 +1,7 @@
import deviceMut from './deviceMut'
import controllerMut from './controllerMut'
export default {
...deviceMut,
...controllerMut,
}
+8
View File
@@ -0,0 +1,8 @@
function newState () {
return {
controllerInfoList: [],
deviceInfoList: [],
}
}
export default newState
+30
View File
@@ -0,0 +1,30 @@
const types = {
controller: {
init: 'initController',
set: 'setController',
setByApi: 'setByApiController',
updateByIndex: 'updateByIndexController',
getByIndex: 'getByIndexController',
getByID: 'getByIDController',
getAll: 'getAllController',
},
device: {
init: 'initDevice',
remove: 'removeDevice',
reorder: 'reorderDevice',
updateDatabaseByID: 'updateDatabaseByIDDevice',
set: 'setDevice',
setByApi: 'setByApiDevice',
updateByIndex: 'updateByIndexDevice',
getByIndex: 'getByIndexDevice',
getByID: 'getByIDDevice',
getAll: 'getAllDevice',
},
}
export default types
@@ -2,23 +2,30 @@ import newSeries from '@/factories/chart/seriesFactory'
import newChart from '@/factories/chart/chartFactory'
import newTooltip from '@/factories/chart/tooltipFactory'
import newDataZoom from '@/factories/chart/dataZoomFactory'
import types from '@/store/modules/analysis/replay/elite/types'
import types from '@/store/modules/analysis/replay/types'
const typePath = types.chart
// generate x axis format
function makeXAxis (gridIndex, type) {
return {
const xAxis = {
type: type,
gridIndex: gridIndex,
axisLine: { show: false, onZero: false, lineStyle: { color: '#aaa' } },
axisTick: { show: false },
axisLabel: { show: false, showMinLabel: false, showMaxLabel: false, color: '#aaa' },
axisLabel: {
show: false,
showMinLabel: true,
showMaxLabel: true,
color: '#aaa',
},
splitLine: { show: true, lineStyle: { color: '#eee' } },
splitNumber: 5,
scale: true,
min: null,
max: null,
}
return xAxis
}
// generate y axis format
@@ -28,12 +35,13 @@ function makeYAxis (gridIndex, type) {
gridIndex: gridIndex,
axisTick: { show: false },
axisLine: { show: false }, // color: '#ccc' } },
axisLabel: { show: true, color: '#aaa', showMinLabel: false, showMaxLabel: false },
axisLabel: { show: true, color: '#aaa', showMinLabel: true, showMaxLabel: true },
splitLine: { show: true, lineStyle: { color: '#eee' } },
splitNumber: 1,
animation: false,
scale: true,
min: null,
max: null,
min: 'dataMin',
max: 'dataMax',
}
}
@@ -69,50 +77,46 @@ function makeYAxisOverview (gridIndex, type) {
}
// get legend name
function getLegendName (sourceList, formulaID) {
function getLegendName (sourceList) {
let legendName = ''
if (formulaID == null) {
// source only 2 device
sourceList.forEach(source => {
switch (source.name) {
case 'Time':
legendName += 'T'
break
case 'Neulive':
legendName += '' + source.id + 'CH' + source.channel
break
case 'Elite':
switch (source.channel) {
case 0:
legendName += '' + source.id + '-I'
break
case 1:
legendName += '' + source.id + '-V'
break
case 2:
legendName += '' + source.id + '-R'
break
default:
legendName += '' + source.id + 'CH' + source.channel
break
}
break
default:
legendName += '' + source.id + 'CH' + source.channel
break
}
legendName += '_'
})
legendName = legendName.substr(0, legendName.length - 1)
} else {
legendName = 'T_F' + formulaID
}
// source only 2 device
sourceList.forEach(source => {
switch (source.name) {
case 'Time':
legendName += 'T'
break
case 'Neulive':
legendName += '' + source.id + 'CH' + String(parseInt(source.channel) + 1)
break
case 'Elite':
switch (source.channel) {
case 1:
legendName += '' + source.id + '-I'
break
case 2:
legendName += '' + source.id + '-V'
break
case 3:
legendName += '' + source.id + '-R'
break
default:
legendName += '' + source.id + 'CH' + source.channel
break
}
break
default:
legendName += '' + source.id + 'CH' + source.channel
break
}
legendName += '_'
})
legendName = legendName.substr(0, legendName.length - 1)
return legendName
}
// generate grid
function makeGrid (index, length, chartID) {
const _height = (82 / length) + '%'
const _height = (82 / length) - 2 + '%'
const _top = index * (82 / length) + 1 + '%'
let _left
let _right
@@ -120,7 +124,7 @@ function makeGrid (index, length, chartID) {
_left = '0%'
_right = '0%'
} else {
_left = '15%'
_left = '8%'
_right = '4%'
}
return {
@@ -141,14 +145,20 @@ const actions = {
* @param {object} chartAllData
* @param {int} chartID : chart id
* @param {int} gridLength : length of chart grid
* @param {string} type
* @param {string} device
* @param {string} mode
* @return {object} : chart data
*/
[typePath.init]: ({ state, getters, commit, dispatch }, payload) => {
if (payload.chartAllData[payload.chartID] == null) {
payload.chartAllData[payload.chartID] = newChart(payload.chartID)
if (payload.chartID !== 0) {
if (payload.type !== 'overview') {
payload.chartAllData[payload.chartID].tooltip = newTooltip()
}
payload.chartAllData[payload.chartID].chartType = payload.type
payload.chartAllData[payload.chartID].chartDevice = payload.device
payload.chartAllData[payload.chartID].chartMode = payload.mode
dispatch(typePath.updateGridList, { chartAllData: payload.chartAllData, chartID: payload.chartID, gridLength: payload.gridLength })
return payload.chartAllData[payload.chartID]
@@ -186,7 +196,7 @@ const actions = {
_series.length = 0
}
delete payload.chartAllData[payload.chartID]
dispatch(typePath.init, { chartAllData: payload.chartAllData, chartID: payload.chartID, gridLength: 1 })
dispatch(typePath.init, { chartAllData: payload.chartAllData, chartID: payload.chartID, gridLength: payload.gridLength })
},
/**
@@ -214,13 +224,24 @@ const actions = {
// update dataZoom AxisIndex list
const dataZoomXAxisIndex = Array.apply(null, { length: payload.chartAllData[payload.chartID].xAxis.length }).map(Number.call, Number)
const dataZoomYAxisIndex = Array.apply(null, { length: payload.chartAllData[payload.chartID].yAxis.length }).map(Number.call, Number)
if (payload.chartAllData[payload.chartID].dataZoom == null && payload.chartID !== 0) {
if (payload.chartAllData[payload.chartID].dataZoom == null) {
payload.chartAllData[payload.chartID].dataZoom = newDataZoom()
}
if (payload.chartAllData[payload.chartID].dataZoom != null) {
payload.chartAllData[payload.chartID].dataZoom[0].xAxisIndex = dataZoomXAxisIndex
payload.chartAllData[payload.chartID].dataZoom[1].xAxisIndex = dataZoomXAxisIndex
payload.chartAllData[payload.chartID].dataZoom[2].yAxisIndex = dataZoomYAxisIndex
if (payload.chartAllData[payload.chartID].chartType === 'overview') {
if (payload.chartAllData[payload.chartID].dataZoom != null) {
payload.chartAllData[payload.chartID].xAxis.push(makeXAxisOverview(0, 'time'))
payload.chartAllData[payload.chartID].dataZoom[0].xAxisIndex = [payload.chartAllData[payload.chartID].xAxis.length - 1]
payload.chartAllData[payload.chartID].dataZoom[1].xAxisIndex = [payload.chartAllData[payload.chartID].xAxis.length - 1]
payload.chartAllData[payload.chartID].dataZoom.length = 2
payload.chartAllData[payload.chartID].dataZoom[0].height = '80%'
payload.chartAllData[payload.chartID].dataZoom[0].top = '0%'
}
} else {
if (payload.chartAllData[payload.chartID].dataZoom != null) {
payload.chartAllData[payload.chartID].dataZoom[0].xAxisIndex = dataZoomXAxisIndex
payload.chartAllData[payload.chartID].dataZoom[1].xAxisIndex = dataZoomXAxisIndex
payload.chartAllData[payload.chartID].dataZoom[2].yAxisIndex = dataZoomYAxisIndex
}
}
},
@@ -246,15 +267,31 @@ const actions = {
* @param {int} chartID
* @param {string} axis ('x' or 'y')
* @param {int} axisIndex
* @param {object} format
* @param {optional, object} format
*/
[typePath.setAxisValueFormat]: (state, payload) => {
const unit = payload.format.unit // string
const unitScale = payload.format.unitScale // int
let name = '' // string
let unit = '' // string
let unitScale = 1 // int
if (payload.format !== undefined) {
name = payload.format.name // string
unit = payload.format.unit // string
unitScale = payload.format.unitScale // int
}
if (payload.axis === 'x') {
payload.chartAllData[payload.chartID].xAxis[payload.axisIndex].axisLabel.formatter = function (val) {
const label = (val / unitScale).toFixed(2) + unit
return label
if (name !== 'time') {
const label = (val / unitScale).toFixed(2) + unit
return label
} else {
var hr = Math.floor(val / 3600000000)
var min = Math.floor((val - (hr * 3600000000)) / 60000000)
var sec = parseInt((val - (hr * 3600000000) - (min * 60000000)) / 1000000)
while (min.length < 2) { min = '0' + min }
while (sec.length < 2) { sec = '0' + min }
if (hr) hr += 'h'
return hr + min + 'm' + sec + 's'
}
}
} else if (payload.axis === 'y') {
payload.chartAllData[payload.chartID].yAxis[payload.axisIndex].axisLabel.formatter = function (val) {
@@ -273,13 +310,9 @@ const actions = {
* @param {int} deviceNameX
* @param {int} deviceIDX
* @param {int} channelX
* @param {object} valueFormatX // { unit: string, unitScale: int}
* @param {int} deviceNameY
* @param {int} deviceIDY
* @param {int} channelY
* @param {object} valueFormatY // { unit: string, unitScale: int}
* @param {int} formula
*
* @return {object} : chart data
*/
[typePath.register]: ({ state, getters, commit, dispatch }, payload) => {
@@ -305,7 +338,7 @@ const actions = {
let xAxisSource
let yAxisSource
const legendName = getLegendName(sourceList, null)
const legendName = getLegendName(sourceList)
switch (sourceList[0].name) {
case 'Time':
@@ -335,8 +368,7 @@ const actions = {
}
// push legendName
chartData.legend.data.push(payload.legendName)
chartData.legend.data.push(legendName)
// if AxisIndex != -1 then add new axis into list
let _xAxisIndex = -1
let _yAxisIndex = -1
@@ -370,18 +402,12 @@ const actions = {
_yAxisIndex = chartData.yAxis.length - 1
}
dispatch(typePath.updateDataZoom, { chartAllData: payload.chartAllData, chartID: payload.chartID })
// dispatch(typePath.updateDataZoom, { chartAllData: payload.chartAllData, chartID: payload.chartID })
// register series
const _series = newSeries('line', legendName, _xAxisIndex, _yAxisIndex, xAxisSource, yAxisSource, null, [])
const _series = newSeries('line', legendName, _xAxisIndex, _yAxisIndex, xAxisSource, yAxisSource, null, null)
chartData.series.push(_series)
// set xAxis format
dispatch(typePath.setAxisValueFormat, { chartAllData: payload.chartAllData, chartID: payload.chartID, axis: 'x', axisIndex: _xAxisIndex, format: payload.valueFormatX })
// set yAxis format
dispatch(typePath.setAxisValueFormat, { chartAllData: payload.chartAllData, chartID: payload.chartID, axis: 'y', axisIndex: _yAxisIndex, format: payload.valueFormatY })
// register series into grid
const _axisList = []
@@ -399,13 +425,13 @@ const actions = {
break
case 'Elite':
switch (source.channel) {
case 0:
case 1:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CURRENT')
break
case 1:
case 2:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' VOLTAGE')
break
case 2:
case 3:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' RESISTANCE')
break
default:
@@ -426,10 +452,23 @@ const actions = {
}
chartData.grid[payload.gridIndex].series.push(_gridSeries)
// console.log(chartData)
return chartData
},
/**
* reset chart axis label
*
* @param {object} chartData
*/
[typePath.resetChartDataAxisLabel]: async (state, payload) => {
const axisArray = payload.chartData.yAxis
for (let index = 0; index < axisArray.length; ++index) {
payload.chartData.yAxis[index].max = null
payload.chartData.yAxis[index].min = null
}
},
// /**
// * remove device-channel from chart TODO
// *
@@ -1,4 +1,4 @@
import types from '@/store/modules/analysis/replay/elite/types'
import types from '@/store/modules/analysis/replay/types'
const typePath = types.meta
@@ -12,7 +12,7 @@ const metaActs = {
*/
[typePath.init]: async ({ state, getters, commit }, payload) => {
const promises = payload.metaIDList.map(async id => {
const metaRes = await payload.api.getMetaFilesByID(id)
const metaRes = await payload.api.meta.getByID(id)
return metaRes.data[0]
})
const list = await Promise.all(promises)
@@ -1,4 +1,4 @@
import types from '@/store/modules/analysis/replay/elite/types'
import types from '@/store/modules/analysis/replay/types'
const typePath = types.rec
@@ -26,13 +26,13 @@ const recActs = {
const getRawInfo = metaList.map(async meta => {
const getData = JSON.parse(meta.channels).map(async ch => {
const res = await payload.api.getRawFilesAttrByParent(ch, meta.id, 'id-start_time-end_time-size')
const res = await payload.api.raw.getAttrByParent(ch, meta.id, 'id-start_time-end_time')
res.data.forEach(_data => {
_data.load = false
_data.data = []
if (parseInt(_data.end_time) <= parseInt(meta.time_duration)) {
if (parseInt(_data.end_time) < 0) {
_data.end_time = meta.time_duration
_data.end_time = parseInt(meta.time_duration)
}
_rec[meta.id][ch][1].push(_data)
}
@@ -47,21 +47,22 @@ const recActs = {
const getData = JSON.parse(meta.channels).map(async ch => {
const miniIDs = Object.values(meta.mini_data[ch])
const combineMiniIDs = [].concat.apply([], miniIDs)
for (const id of combineMiniIDs) {
const res = await payload.api.getMiniFilesAttrByID(ch, id, 'id-start_time-end_time-scale-size')
const res = await payload.api.mini.getAttrByID(ch, id, 'id-start_time-end_time-scale')
res.data.forEach(_data => {
_data.load = false
_data.data = []
if (parseInt(_data.end_time) <= parseInt(meta.time_duration)) {
if (parseInt(_data.end_time) < 0) {
_data.end_time = meta.time_duration
_data.end_time = parseInt(meta.time_duration)
}
// console.log(meta.id, ch, parseInt(_data.scale), _data)
_rec[meta.id][ch][parseInt(_data.scale)].push(_data)
}
})
}
// const res = await payload.api.getMiniFilesAttrByParent(ch, meta.id, 'id-start_time-end_time-scale')
// const res = await payload.api.mini.getAttrByParent(ch, meta.id, 'id-start_time-end_time-scale')
// res.data.forEach(_data => {
// _data.load = false
// _data.data = []
@@ -97,10 +98,27 @@ const recActs = {
})
},
/**
* into data to rec
*
* @param {int} meta
* @param {str} device
*/
[typePath.initDisplaySetting]: async ({ state, getters, commit }, payload) => {
commit(typePath.initDisplaySetting, {
meta: payload.meta,
})
switch (payload.device) {
case 'Neulive':
commit(typePath.initDisplaySettingNeulive, {
meta: payload.meta,
})
break
case 'Elite':
commit(typePath.initDisplaySettingElite, {
meta: payload.meta,
})
break
default:
break
}
},
[typePath.updateDisplaySetting]: async ({ state, getters, commit }, payload) => {
@@ -1,267 +0,0 @@
import types from '@/store/modules/analysis/replay/elite/types'
import { newChartMode } from '@/factories/chart/chartFactory'
const typePath = types.rec
const recMutations = {
/**
* set rec list
*
* @param {object} data
*/
[typePath.set]: async (state, payload) => {
state.recInfo = payload.data
},
/**
* Updates the rec info by index
*
* @param {any} item
*/
[typePath.update]: function (state, payload) {
for (const item in payload) {
state.recInfo[item] = payload[item]
}
},
/**
* update data rec
*
* @param {int} index
* @param {int} metaID
* @param {int} channel
* @param {int} scale
* @param {object} data
*/
[typePath.updateDataByIndex]: function (state, payload) {
state.recInfo[payload.metaID][payload.channel][payload.scale][payload.index].data = payload.data
state.recInfo[payload.metaID][payload.channel][payload.scale][payload.index].load = true
},
/**
* init rec display setting
*
* @param {object} meta
*/
[typePath.initDisplaySetting]: function (state, payload) {
state.displaySettingInfo.valueRanges = []
for (const key of Object.keys(payload.meta.mini_data)) {
if (parseInt(key) < 255) {
state.displaySettingInfo.valueRanges.push({ id: parseInt(key), name: 'ch ' + parseInt(key), xMin: '', xMax: '', yMin: '', yMax: '', showXMin: false, showXMax: false, showYMin: false, showYMax: false })
} else if (parseInt(key) === 256) {
state.displaySettingInfo.valueRanges.push({ id: parseInt(key), name: 'x', xMin: '', xMax: '', yMin: '', yMax: '', showXMin: false, showXMax: false, showYMin: false, showYMax: false })
} else if (parseInt(key) === 257) {
state.displaySettingInfo.valueRanges.push({ id: parseInt(key), name: 'y', xMin: '', xMax: '', yMin: '', yMax: '', showXMin: false, showXMax: false, showYMin: false, showYMax: false })
} else if (parseInt(key) === 258) {
state.displaySettingInfo.valueRanges.push({ id: parseInt(key), name: 'z', xMin: '', xMax: '', yMin: '', yMax: '', showXMin: false, showXMax: false, showYMin: false, showYMax: false })
} else if (parseInt(key) === 259) {
state.displaySettingInfo.valueRanges.push({ id: parseInt(key), name: 'magnitude', xMin: '', xMax: '', yMin: '', yMax: '', showXMin: false, showXMax: false, showYMin: false, showYMax: false })
}
}
state.displaySettingInfo.channelXOptions = [
{
id: 0,
description: 'Current',
},
{
id: 1,
description: 'Voltage',
},
{
id: 2,
description: 'Resistance',
},
{
id: 3,
description: 'Time',
},
]
state.displaySettingInfo.channelYOptions = [
{
id: 0,
description: 'Current',
},
{
id: 1,
description: 'Voltage',
},
{
id: 2,
description: 'Resistance',
},
]
state.displaySettingInfo.scaleOptions = [
{
id: 0,
description: 'Linear',
},
{
id: 1,
description: 'Log',
},
]
state.displaySettingInfo.valueFormatOptions = {
0: [ // Current
{
id: 0,
unit: 'nA',
unitScale: 1,
},
{
id: 1,
unit: 'uA',
unitScale: 1000,
},
{
id: 2,
unit: 'mA',
unitScale: 1000000,
},
],
1: [ // Voltage
{
id: 0,
unit: 'uV',
unitScale: 1,
},
{
id: 1,
unit: 'mV',
unitScale: 1000,
},
{
id: 2,
unit: 'V',
unitScale: 1000000,
},
],
2: [ // Resistance
{
id: 0,
unit: 'kohm',
unitScale: 1,
},
{
id: 1,
unit: 'ohm',
unitScale: 0.001,
},
{
id: 2,
unit: 'Mohm',
unitScale: 1000,
},
],
3: [ // Time
{
id: 0,
unit: 'us',
unitScale: 1,
},
{
id: 1,
unit: 'ms',
unitScale: 1000,
},
{
id: 2,
unit: 's',
unitScale: 1000000,
},
],
}
const setting = newChartMode(payload.meta.parameter_set.MODE)
const xType = setting[0]
const xValue = setting[1]
const yType = setting[2]
const yValue = setting[3]
if (xType === 'Elite') {
// 1: I, 2: V, 3: R
if (xValue === 1) {
state.displaySettingInfo.valueFormatX = { id: 0, unit: 'nA', unitScale: 1 }
state.displaySettingInfo.channelXSelect = { id: 0, description: 'Current' }
} else if (xValue === 2) {
state.displaySettingInfo.valueFormatX = { id: 0, unit: 'uV', unitScale: 1 }
state.displaySettingInfo.channelXSelect = { id: 1, description: 'Voltage' }
} else if (xValue === 3) {
state.displaySettingInfo.valueFormatX = { id: 0, unit: 'kohm', unitScale: 1 }
state.displaySettingInfo.channelXSelect = { id: 2, description: 'Resistance' }
}
} else if (xType === 'Time') {
state.displaySettingInfo.valueFormatX = { id: 0, unit: 'us', unitScale: 1 }
state.displaySettingInfo.channelXSelect = { id: 3, description: 'Time' }
}
if (yType === 'Elite') {
// 1: I, 2: V, 3: R
if (yValue === 1) {
state.displaySettingInfo.valueFormatY = { id: 0, unit: 'nA', unitScale: 1 }
state.displaySettingInfo.channelYSelect = { id: 0, description: 'Current' }
} else if (yValue === 2) {
state.displaySettingInfo.valueFormatY = { id: 0, unit: 'uV', unitScale: 1 }
state.displaySettingInfo.channelYSelect = { id: 1, description: 'Voltage' }
} else if (yValue === 3) {
state.displaySettingInfo.valueFormatY = { id: 0, unit: 'kohm', unitScale: 1 }
state.displaySettingInfo.channelYSelect = { id: 2, description: 'Resistance' }
}
}
state.displaySettingInfo.scaleXSelect = { id: 0, description: 'Linear' }
state.displaySettingInfo.scaleYSelect = { id: 0, description: 'Linear' }
state.displaySettingInfo.ignoreGridIndex = []
state.displaySettingInfo.filename = payload.meta.name
const params = payload.meta.parameter_set
state.displaySettingInfo.parameterInfo = { recording: '' }
state.displaySettingInfo.parameterInfo.recording += 'Duration: ' + parseInt(parseInt(payload.meta.time_duration / 1000000) / 60) + ' m ' + parseInt((payload.meta.time_duration % 60000000) / 1000000) + ' s<br/>'
state.displaySettingInfo.parameterInfo.recording += '<br/>Parameter: <br/>'
for (const [key, value] of Object.entries(params)) {
if (!(key.includes('sti') || key.includes('STI'))) {
state.displaySettingInfo.parameterInfo.recording += ' ' + key + ': ' + value + '<br/>'
}
}
state.displaySettingInfo.editInfo = {
info: { id: payload.meta.id },
changedName: '',
success: false,
error: false,
errorMessagesAll: ['File name contains illegal character', 'File name empty', 'File name exist'],
errorMessages: [],
}
state.displaySettingInfo.deleteInfo = {
path: '',
name: '',
metaID: payload.meta.id,
rawChannelAndIDArrays: [], // list of lists
miniChannelAndIDArrays: [], // list of lists
}
},
/**
* update rec display setting
*
* @param {object} updateObject { settingInfoKey, value (object) }
*/
[typePath.updateDisplaySetting]: function (state, payload) {
const infoNames = Object.keys(payload.updateObject)
for (const infoName of infoNames) {
const _object = payload.updateObject[infoName]
if (Array.isArray(state.displaySettingInfo[infoName])) {
const id = _object.id
const index = state.displaySettingInfo[infoName].findIndex(x => x.id === id)
for (const [key, value] of Object.entries(_object)) {
state.displaySettingInfo[infoName][index][key] = value
}
} else {
state.displaySettingInfo[infoName] = _object
}
}
},
}
export default recMutations
@@ -1,60 +0,0 @@
const types = {
chart: {
init: 'initChart',
reset: 'resetChart',
register: 'registerChart',
remove: 'removeChart',
clear: 'clearChart',
getDataByID: 'getDataByIDChart',
getAllData: 'getAllDataChart',
setChartData: 'setChartDataChart',
setTooltip: 'setTooltipChart',
setMarkArea: 'setMarkAreaChart',
setMarkAreaData: 'setMarkAreaDataChart',
setDataZoom: 'setDataZoomChart',
updateDataZoom: 'updateDataZoomChart',
updateGridList: 'updateGridListChart',
pushSeries: 'pushSeriesChart',
pushAxis: 'pushAxisChart',
pushLegendName: 'pushLegendNameChart',
setTimeXAxis: 'setTimeXAxisChart',
setAxisValueFormat: 'setAxisValueFormatChart',
pushGridSeries: 'pushGridSeriesChart',
deleteByID: 'deleteByIDChart',
update: 'updateChart',
updateSeries: 'updateSeriesChart',
updateAxis: 'updateAxisChart',
updateSeriesData: 'updateSeriesDataChart',
},
meta: {
init: 'initMeta',
set: 'setMeta',
setByApi: 'setByApiMeta',
updateByIndex: 'updateByIndexMeta',
getByIndex: 'getByIndexMeta',
getByID: 'getByIDMeta',
getAll: 'getAllMeta',
},
rec: {
init: 'initRec',
intoData: 'intoDataRec',
initDisplaySetting: 'initDisplaySettingRec',
set: 'setRec',
update: 'updateRec',
updateDataByIndex: 'updateDataByIndexRec',
updateDisplaySetting: 'updateDisplaySettingRec',
getAll: 'getAllRec',
getAllDisplaySetting: 'getAllDisplaySettingRec',
getDisplaySettingByKey: 'getDisplaySettingByKeyRec',
},
}
export default types
@@ -1,4 +1,4 @@
import types from '@/store/modules/analysis/replay/elite/types'
import types from '@/store/modules/analysis/replay/types'
const typePath = types.meta
@@ -1,4 +1,4 @@
import types from '@/store/modules/analysis/replay/elite/types'
import types from '@/store/modules/analysis/replay/types'
const typePath = types.rec
@@ -0,0 +1,254 @@
import types from '@/store/modules/analysis/replay/types'
const typePath = types.chart
// get legend name
function getLegendName (sourceList) {
let legendName = ''
// source only 2 device
sourceList.forEach(source => {
switch (source.name) {
case 'Time':
legendName += 'T'
break
case 'Neulive':
legendName += '' + source.id + 'CH' + String(parseInt(source.channel) + 1)
break
case 'Elite':
switch (source.channel) {
case 1:
legendName += '' + source.id + '-I'
break
case 2:
legendName += '' + source.id + '-V'
break
case 3:
legendName += '' + source.id + '-R'
break
default:
legendName += '' + source.id + 'CH' + source.channel
break
}
break
default:
legendName += '' + source.id + 'CH' + source.channel
break
}
legendName += '_'
})
legendName = legendName.substr(0, legendName.length - 1)
return legendName
}
const chartMutations = {
/**
* update label formatter
*
* @param {int} chartID
* @param {string} axis ('x' or 'y')
* @param {int} axisIndex
*/
[typePath.updateAxisLabel]: (state, payload) => {
let unit // string
let unitScale // int
let axisLabel
if (payload.axis === 'x') {
unit = state.valueFormatX.unit
unitScale = state.valueFormatX.unitScale
axisLabel = state.chartData[payload.chartID].xAxis[payload.axisIndex].axisLabel
} else if (payload.axis === 'y') {
unit = state.valueFormatY.unit
unitScale = state.valueFormatY.unitScale
axisLabel = state.chartData[payload.chartID].yAxis[payload.axisIndex].axisLabel
}
axisLabel.formatter = function (val) {
let label = ''
if (unit === 'auto') { // time
const hour = parseInt(val / 3.6e9)
const minute = parseInt((val % 3.6e9) / 1000000 / 60)
const second = parseInt((val % 6e7) / 1000000)
const millisecond = parseInt((val % 1e6) / 1000)
if (hour > 0) {
label += hour + ' h '
}
if (minute > 0) {
label += minute + ' m '
}
if (second > 0) {
label += second + ' s '
}
if (millisecond > 0) {
label += millisecond + ' ms '
}
} else { // not time, e.g. I, V, R
const num = val / unitScale
if (Math.abs(num) >= 1e+6) {
label = num.toExponential(3) + unit
} else {
label = num.toFixed(1) + unit
}
}
return label
}
},
/**
* turn on/off axis event handler
*
* @param {int} chartID
* @param {string} axis ('x' or 'y')
* @param {bool} status (on/off)
*/
[typePath.updateAxisEventHandler]: (state, payload) => {
let _axis
if (payload.axis === 'x') {
_axis = state.chartData[payload.chartID].xAxis
} else if (payload.axis === 'y') {
_axis = state.chartData[payload.chartID].yAxis
}
const len = _axis.length
if (payload.status === 'on') {
for (let i = 0; i < len; i++) {
_axis[i].triggerEvent = true
}
} else if (payload.status === 'off') {
for (let i = 0; i < len; i++) {
_axis[i].triggerEvent = false
}
}
},
/**
* update axis value min & max
*
* @param {int} chartID
* @param {string} axis ('x' or 'y')
* @param {int} axisIndex
* @param {float} minVal
* @param {float} maxVal
*/
[typePath.updateAxisValMinMax]: (state, payload) => {
let grid
if (payload.axis === 'x') {
grid = state.chartData[payload.chartID].xAxis[payload.axisIndex]
} else if (payload.axis === 'y') {
grid = state.chartData[payload.chartID].yAxis[payload.axisIndex]
}
if (payload.minVal !== '') {
grid.min = payload.minVal
} else {
grid.min = 'dataMin'
}
if (payload.maxVal !== '') {
grid.max = payload.maxVal
} else {
grid.max = 'dataMax'
}
},
/**
* update series by cycle
*
* @param {int} chartID
* @param {int} seriesIndex
* @param {array} data
*/
[typePath.updateSeries]: (state, payload) => {
state.chartData[payload.chartID].series[payload.seriesIndex].data = payload.data
},
/**
* update registered chartData
*
* @param {object} chartAllData
* @param {int} chartID : chart id
* @param {int} gridIndex : index of grid
* @param {int} deviceNameX
* @param {int} deviceIDX
* @param {int} channelX
* @param {int} deviceNameY
* @param {int} deviceIDY
* @param {int} channelY
* @return {object} : chart data
*/
[typePath.updateRegistered]: ({ state, getters, commit, dispatch }, payload) => {
const chartData = payload.chartAllData[payload.chartID]
const sourceList = [
{
name: payload.deviceNameX,
id: payload.deviceIDX,
channel: payload.channelX,
},
{
name: payload.deviceNameY,
id: payload.deviceIDY,
channel: payload.channelY,
},
]
if (chartData == null) {
return false
}
const legendName = getLegendName(sourceList)
// register legendName
if (chartData.legend.data.indexOf(legendName) >= 0) {
// have been registered
return false
}
// push legendName
chartData.legend.data[payload.gridIndex] = legendName
// register series into grid
const _axisList = []
sourceList.forEach((source, index) => {
let _axis = 'X'
if (index !== 0) {
_axis = 'Y'
}
switch (source.name) {
case 'Time':
_axisList.push(_axis + ' AXIS = TIME')
break
case 'Neulive':
_axisList.push(_axis + ' AXIS = NEULIVE ' + source.id + ' CHANNEL ' + source.channel)
break
case 'Elite':
switch (source.channel) {
case 1:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CURRENT')
break
case 2:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' VOLTAGE')
break
case 3:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' RESISTANCE')
break
default:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CHANNEL ' + source.channel)
break
}
break
default:
_axisList.push(_axis + ' AXIS = DEVICE ' + source.id + ' CHANNEL ' + source.channel)
break
}
})
const _gridSeries = {
name: legendName,
xAxis: _axisList[0],
yAxis: _axisList[1],
}
chartData.grid[payload.gridIndex].series[payload.gridIndex] = _gridSeries
chartData.series[payload.gridIndex].name = legendName
return chartData
},
}
export default chartMutations
@@ -1,8 +1,10 @@
import chartMut from './chartMut'
import metaMut from './metaMut'
import recMut from './recMut'
import { updateField } from 'vuex-map-fields'
export default {
...chartMut,
...metaMut,
...recMut,
updateField,
@@ -1,4 +1,4 @@
import types from '@/store/modules/analysis/replay/elite/types'
import types from '@/store/modules/analysis/replay/types'
const typePath = types.meta
@@ -0,0 +1,41 @@
import types from '@/store/modules/analysis/replay/types'
const typePath = types.rec
const recMutations = {
/**
* set rec list
*
* @param {object} data
*/
[typePath.set]: async (state, payload) => {
state.recInfo = payload.data
},
/**
* Updates the rec info by index
*
* @param {any} item
*/
[typePath.update]: function (state, payload) {
for (const item in payload) {
state.recInfo[item] = payload[item]
}
},
/**
* update data rec
*
* @param {int} index
* @param {int} metaID
* @param {int} channel
* @param {int} scale
* @param {object} data
*/
[typePath.updateDataByIndex]: function (state, payload) {
state.recInfo[payload.metaID][payload.channel][payload.scale][payload.index].data = payload.data
state.recInfo[payload.metaID][payload.channel][payload.scale][payload.index].load = true
},
}
export default recMutations

Some files were not shown because too many files have changed in this diff Show More