tsviewer 0.1.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/tsviewer.css +1 -0
- package/dist/tsviewer.es.js +21456 -0
- package/dist/tsviewer.umd.js +26 -33259
- package/package.json +35 -32
- package/babel.config.js +0 -5
- package/dist/demo.html +0 -1
- package/dist/tsviewer.common.js +0 -33247
- package/dist/tsviewer.common.js.map +0 -1
- package/dist/tsviewer.umd.js.map +0 -1
- package/dist/tsviewer.umd.min.js +0 -4
- package/dist/tsviewer.umd.min.js.map +0 -1
- package/jsconfig.json +0 -19
- package/public/favicon.ico +0 -0
- package/public/index.html +0 -17
- package/src/App.vue +0 -41
- package/src/assets/icons/blackfynn-amplitude-zoom.js +0 -11
- package/src/assets/icons/blackfynn-timescale.js +0 -11
- package/src/assets/icons/icon-controller-pause.js +0 -11
- package/src/assets/icons/icon-controller-play.js +0 -11
- package/src/assets/icons/icon-next-page.js +0 -11
- package/src/assets/icons/icon-previous-page.js +0 -11
- package/src/assets/icons/icon-stopwatch.js +0 -11
- package/src/assets/icons/index.js +0 -7
- package/src/components/TSPlotCanvas.vue +0 -1868
- package/src/components/TSScrubber.vue +0 -420
- package/src/components/TSViewer.vue +0 -595
- package/src/components/TSViewerCanvas.vue +0 -793
- package/src/components/TSViewerToolbar.vue +0 -356
- package/src/components/index.js +0 -13
- package/src/main.js +0 -23
- package/src/mixins/request/index.js +0 -100
- package/src/mixins/ts-annotation/index.js +0 -202
- package/src/mixins/viewer-active-tool/index.js +0 -36
- package/src/store/index.js +0 -184
- package/src/utils/constants.js +0 -15
- package/vue.config.js +0 -12
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="timeseries-viewer-toolbar">
|
|
3
|
-
<div id="left-controls">
|
|
4
|
-
<el-tooltip
|
|
5
|
-
placement="top-end"
|
|
6
|
-
content="Toggle Time Zoom Controls">
|
|
7
|
-
<button
|
|
8
|
-
class="btn-icon"
|
|
9
|
-
@click="toggleTimeZoom()">
|
|
10
|
-
<svg
|
|
11
|
-
class="svg-fill icon"
|
|
12
|
-
width="20"
|
|
13
|
-
height="20"
|
|
14
|
-
viewBox="0 0 16 16"
|
|
15
|
-
>
|
|
16
|
-
<path d="M13.653125,14.3537502 L11.29125,11.9918752 C11.6475,11.4075002 11.8525,10.7200002 11.8525,9.98562517 C11.8525,7.85000017 10.001875,6.00000017 7.86625,6.00000017 C5.730625,5.99937517 4,7.73062517 4,9.86625017 C4,12.0012502 5.850625,13.8518752 7.985625,13.8518752 C8.69625,13.8518752 9.360625,13.6587502 9.9325,13.3243752 L12.306875,15.7000002 C12.539375,15.9318752 12.91625,15.9318752 13.148125,15.7000002 L13.7375,15.1106252 C13.969375,14.8787502 13.885,14.5856252 13.653125,14.3537502 Z M5.19,9.86625017 C5.19,8.38750017 6.388125,7.18937517 7.86625,7.18937517 C9.345,7.18937517 10.6625,8.50625017 10.6625,9.98562517 C10.6625,11.4637502 9.46375,12.6625002 7.985625,12.6625002 C6.506875,12.6618752 5.19,11.3443752 5.19,9.86625017 Z M16,3 L13,6 L13,4 L9,4 L9,2 L13,2 L13,6.2778623e-16 L16,3 Z M3,6 L2.66453526e-15,3 L3,-7.66951701e-17 L3,2 L9,2 L9,4 L3,4 L3,6 Z"/>
|
|
17
|
-
</svg>
|
|
18
|
-
</button>
|
|
19
|
-
</el-tooltip>
|
|
20
|
-
|
|
21
|
-
<el-input-number
|
|
22
|
-
v-model="durationInSeconds"
|
|
23
|
-
v-if="showTimeZoom"
|
|
24
|
-
:precision="1"
|
|
25
|
-
:step="5"
|
|
26
|
-
:max="this.constants['MAXDURATION']"
|
|
27
|
-
size="mini"
|
|
28
|
-
controls-position="right">
|
|
29
|
-
</el-input-number>
|
|
30
|
-
|
|
31
|
-
<el-tooltip
|
|
32
|
-
placement="top-end"
|
|
33
|
-
content="Toggle Vertical Zoom Controls">
|
|
34
|
-
<button
|
|
35
|
-
class="btn-icon"
|
|
36
|
-
@click="toggleVerticalZoom()">
|
|
37
|
-
<svg
|
|
38
|
-
class="svg-fill icon"
|
|
39
|
-
width="20"
|
|
40
|
-
height="20"
|
|
41
|
-
viewBox="0 0 16 16"
|
|
42
|
-
>
|
|
43
|
-
<path d="M15.715625,12.416875 L13.35375,10.055 C13.71,9.470625 13.915,8.783125 13.915,8.04875 C13.915,5.913125 12.064375,4.063125 9.92875,4.063125 C7.793125,4.0625 6.0625,5.79375 6.0625,7.929375 C6.0625,10.064375 7.913125,11.915 10.048125,11.915 C10.75875,11.915 11.423125,11.721875 11.995,11.3875 L14.369375,13.763125 C14.601875,13.995 14.97875,13.995 15.210625,13.763125 L15.8,13.17375 C16.031875,12.941875 15.9475,12.64875 15.715625,12.416875 Z M7.2525,7.929375 C7.2525,6.450625 8.450625,5.2525 9.92875,5.2525 C11.4075,5.2525 12.725,6.569375 12.725,8.04875 C12.725,9.526875 11.52625,10.725625 10.048125,10.725625 C8.569375,10.725 7.2525,9.4075 7.2525,7.929375 Z M3,0 L6,3 L4,3 L4,7 L2,7 L2,3 L0,3 L3,0 Z M6,13 L3,16 L0,13 L2,13 L2,7 L4,7 L4,13 L6,13 Z"/>
|
|
44
|
-
</svg>
|
|
45
|
-
</button>
|
|
46
|
-
</el-tooltip>
|
|
47
|
-
|
|
48
|
-
<el-button-group v-if="showVertZoom">
|
|
49
|
-
<el-button icon="el-icon-plus" size="mini" @click="incrementZoom"></el-button>
|
|
50
|
-
<el-button icon="el-icon-minus" size="mini" @click="decrementZoom"></el-button>
|
|
51
|
-
</el-button-group>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<div id="center-controls">
|
|
55
|
-
<el-tooltip
|
|
56
|
-
placement="top-end"
|
|
57
|
-
content="Page Back">
|
|
58
|
-
<button
|
|
59
|
-
class="btn-icon"
|
|
60
|
-
@click="pageBack()">
|
|
61
|
-
<svg
|
|
62
|
-
class="svg-fill icon"
|
|
63
|
-
width="18"
|
|
64
|
-
height="12"
|
|
65
|
-
viewBox="0 0 12 12"
|
|
66
|
-
>
|
|
67
|
-
<path d="M10.959,0.571 L3.756,5.52 C3.756,5.52 3.477,5.721 3.477,6.001 C3.477,6.281 3.756,6.48 3.756,6.48 L10.959,11.431 C11.531,11.811 12,11.53 12,10.805 L12,1.196 C12,0.469 11.531,0.188 10.959,0.571 Z M2,0 L1,0 C0.447,0 0,0.048 0,0.6 L0,11.4 C0,11.952 0.447,12 1,12 L2,12 C2.553,12 3,11.952 3,11.4 L3,0.6 C3,0.048 2.553,0 2,0 Z"/>
|
|
68
|
-
</svg>
|
|
69
|
-
</button>
|
|
70
|
-
</el-tooltip>
|
|
71
|
-
<!--
|
|
72
|
-
<el-tooltip
|
|
73
|
-
placement="top-end"
|
|
74
|
-
content="Previous Annotation">
|
|
75
|
-
<button
|
|
76
|
-
class="btn-icon"
|
|
77
|
-
@click="previousAnnotation()">
|
|
78
|
-
<svg-icon
|
|
79
|
-
name="next-annotation-left-facing"
|
|
80
|
-
height="12"
|
|
81
|
-
width="18"/>
|
|
82
|
-
</button>
|
|
83
|
-
</el-tooltip> -->
|
|
84
|
-
|
|
85
|
-
<el-tooltip
|
|
86
|
-
placement="top-end"
|
|
87
|
-
content="Automatic Forward">
|
|
88
|
-
<button
|
|
89
|
-
class="btn-icon"
|
|
90
|
-
@click="togglePlayback()">
|
|
91
|
-
<svg
|
|
92
|
-
v-if="isPlaying"
|
|
93
|
-
class="svg-fill icon"
|
|
94
|
-
width="18"
|
|
95
|
-
height="12"
|
|
96
|
-
viewBox="0 0 10 12"
|
|
97
|
-
>
|
|
98
|
-
<path d="M2,0 C2.553,0 3,0.048 3,0.6 L3,11.4 C3,11.952 2.553,12 2,12 L1,12 C0.447,12 0,11.952 0,11.4 L0,0.6 C0,0.048 0.447,0 1,0 L2,0 Z M9,0 C9.553,0 10,0.048 10,0.6 L10,11.4 C10,11.952 9.553,12 9,12 L8,12 C7.447,12 7,11.952 7,11.4 L7,0.6 C7,0.048 7.447,0 8,0 L9,0 Z"/>
|
|
99
|
-
</svg>
|
|
100
|
-
<svg
|
|
101
|
-
v-else
|
|
102
|
-
class="svg-fill icon"
|
|
103
|
-
width="18"
|
|
104
|
-
height="12"
|
|
105
|
-
viewBox="0 0 10 12"
|
|
106
|
-
>
|
|
107
|
-
<path d='M10,6.001 C10,6.3 9.695,6.515 9.695,6.515 L1.134,11.818 C0.51,12.227 0,11.924 0,11.149 L0,0.852 C0,0.075 0.51,-0.226 1.135,0.182 L9.696,5.487 C9.695,5.487 10,5.702 10,6.001 Z'/>
|
|
108
|
-
</svg>
|
|
109
|
-
</button>
|
|
110
|
-
</el-tooltip>
|
|
111
|
-
<!--
|
|
112
|
-
<el-tooltip
|
|
113
|
-
placement="top-end"
|
|
114
|
-
content="Next Annotation">
|
|
115
|
-
<button
|
|
116
|
-
class="btn-icon"
|
|
117
|
-
@click="nextAnnotation()">
|
|
118
|
-
<svg-icon
|
|
119
|
-
name="next-annotation-right-facing"
|
|
120
|
-
height="12"
|
|
121
|
-
width="18"/>
|
|
122
|
-
</button>
|
|
123
|
-
|
|
124
|
-
</el-tooltip> -->
|
|
125
|
-
|
|
126
|
-
<el-tooltip
|
|
127
|
-
placement="top-end"
|
|
128
|
-
content="Next Page">
|
|
129
|
-
<button
|
|
130
|
-
class="btn-icon"
|
|
131
|
-
@click="pageForward()">
|
|
132
|
-
<svg
|
|
133
|
-
class="svg-fill icon"
|
|
134
|
-
width="18"
|
|
135
|
-
height="12"
|
|
136
|
-
viewBox="0 0 12 12"
|
|
137
|
-
>
|
|
138
|
-
<path d="M8.244,5.52 L1.041,0.571 C0.469,0.188 0,0.469 0,1.196 L0,10.805 C0,11.53 0.469,11.811 1.041,11.43 L8.244,6.479 C8.244,6.479 8.523,6.28 8.523,6.001 C8.523,5.721 8.244,5.52 8.244,5.52 Z M10,0 L11,0 C11.553,0 12,0.048 12,0.6 L12,11.4 C12,11.952 11.553,12 11,12 L10,12 C9.447,12 9,11.952 9,11.4 L9,0.6 C9,0.048 9.447,0 10,0 Z"/>
|
|
139
|
-
</svg>
|
|
140
|
-
</button>
|
|
141
|
-
</el-tooltip>
|
|
142
|
-
</div>
|
|
143
|
-
<div id="right-controls">
|
|
144
|
-
<!-- <el-tooltip-->
|
|
145
|
-
<!-- placement="top-end"-->
|
|
146
|
-
<!-- content="Montaging Controls">-->
|
|
147
|
-
<!-- <el-select v-model="selectedMontage" placeholder="Select" size="mini" @change="updateMontageScheme">-->
|
|
148
|
-
<!-- <el-option-->
|
|
149
|
-
<!-- v-for="item in montageOptions"-->
|
|
150
|
-
<!-- :key="item.value"-->
|
|
151
|
-
<!-- :label="item.label"-->
|
|
152
|
-
<!-- :value="item.value">-->
|
|
153
|
-
<!-- </el-option>-->
|
|
154
|
-
<!-- </el-select>-->
|
|
155
|
-
<!-- </el-tooltip>-->
|
|
156
|
-
|
|
157
|
-
<el-tooltip
|
|
158
|
-
placement="top-end"
|
|
159
|
-
content="Toggle Play Back Speed Controls">
|
|
160
|
-
<button
|
|
161
|
-
class="btn-icon"
|
|
162
|
-
@click="togglePlaybackSpeed()">
|
|
163
|
-
<svg
|
|
164
|
-
class="svg-fill icon"
|
|
165
|
-
width="22"
|
|
166
|
-
height="20"
|
|
167
|
-
viewBox="0 0 16 16"
|
|
168
|
-
>
|
|
169
|
-
<path d="M5.1008,5.396 C4.7432,5.616 6.0584,8.7896 6.3792,9.3064 C6.6592,9.7616 7.2536,9.9 7.7056,9.6216 C8.16,9.34 8.3016,8.7464 8.0216,8.2936 C7.704,7.7752 5.4576,5.1752 5.1008,5.396 Z M4.8328,1.9216 C5.5752,1.6632 6.3704,1.52 7.2,1.52 C8.0296,1.52 8.8248,1.6632 9.5672,1.9216 C9.8304,2.0128 10.1792,1.8296 10.0248,1.4328 C9.912,1.1448 9.8032,0.8632 9.7592,0.7488 C9.6544,0.4776 9.2792,0.2536 9.116,0.2168 C8.4984,0.0776 7.8584,0 7.2,0 C6.5416,0 5.9016,0.0776 5.2832,0.2168 C5.12,0.2536 4.7456,0.4776 4.6408,0.7488 C4.5968,0.8632 4.4872,1.1448 4.3752,1.4328 C4.2208,1.8296 4.5696,2.0136 4.8328,1.9216 Z M14.4784,2.5488 C14.3248,2.3648 14.1616,2.1848 13.988,2.0112 C13.8152,1.8376 13.6352,1.6752 13.452,1.5208 C13.3296,1.4176 12.9696,1.3336 12.7416,1.5616 C12.5144,1.7896 11.4232,2.8792 11.4232,2.8792 C11.7448,3.1096 12.0576,3.3632 12.3472,3.652 C12.6368,3.9408 12.8888,4.2536 13.12,4.576 C13.12,4.576 14.2104,3.4864 14.4376,3.2584 C14.6664,3.0296 14.5824,2.6704 14.4784,2.5488 Z M7.2,2.32 C3.62,2.32 0.7192,5.2208 0.7192,8.8 C0.7192,12.38 3.62,15.2808 7.2,15.2808 C10.7784,15.2808 13.68,12.38 13.68,8.8 C13.68,5.2216 10.7784,2.32 7.2,2.32 Z M7.2,13.6808 C4.5056,13.6808 2.32,11.496 2.32,8.8008 C2.32,6.1056 4.5048,3.9208 7.2,3.9208 C9.8952,3.9208 12.0808,6.1056 12.0808,8.8008 C12.0808,11.4952 9.8952,13.6808 7.2,13.6808 Z"/>
|
|
170
|
-
</svg>
|
|
171
|
-
</button>
|
|
172
|
-
</el-tooltip>
|
|
173
|
-
|
|
174
|
-
<el-select
|
|
175
|
-
v-model="selectedPlaySpeed"
|
|
176
|
-
v-if="showPlaybackSpeed"
|
|
177
|
-
placeholder="Select"
|
|
178
|
-
size="mini"
|
|
179
|
-
class="playSelect">
|
|
180
|
-
<el-option
|
|
181
|
-
v-for="item in playSpeedOptions"
|
|
182
|
-
:key="item.value"
|
|
183
|
-
:label="item.label"
|
|
184
|
-
:value="item.value">
|
|
185
|
-
</el-option>
|
|
186
|
-
</el-select>
|
|
187
|
-
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
</div>
|
|
191
|
-
</template>
|
|
192
|
-
|
|
193
|
-
<script>
|
|
194
|
-
export default {
|
|
195
|
-
name: 'TimeseriesViewerToolbar',
|
|
196
|
-
computed: {
|
|
197
|
-
durationInSeconds: {
|
|
198
|
-
// getter
|
|
199
|
-
get: function () {
|
|
200
|
-
return this.duration / 1e6
|
|
201
|
-
},
|
|
202
|
-
// setter
|
|
203
|
-
set: function (newValue) {
|
|
204
|
-
this.$emit('updateDuration', newValue)
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
props: {
|
|
209
|
-
constants: Object,
|
|
210
|
-
duration: Number,
|
|
211
|
-
start: Number
|
|
212
|
-
},
|
|
213
|
-
data: function () {
|
|
214
|
-
return {
|
|
215
|
-
showVertZoom: true,
|
|
216
|
-
showTimeZoom: true,
|
|
217
|
-
showPlaybackSpeed: true,
|
|
218
|
-
selectedTimeRange: 0,
|
|
219
|
-
isPlaying: false,
|
|
220
|
-
montageOptions: [{
|
|
221
|
-
value: 'NOT_MONTAGED',
|
|
222
|
-
label: 'Continuous (Default)'
|
|
223
|
-
}, {
|
|
224
|
-
value: 'REFERENTIAL_VS_CZ',
|
|
225
|
-
label: 'Referential Montage'
|
|
226
|
-
}, {
|
|
227
|
-
value: 'BIPOLAR_ANT_POS',
|
|
228
|
-
label: 'Ant/Post Montage'
|
|
229
|
-
}, {
|
|
230
|
-
value: 'BIPOLAR_TRANSVERSE',
|
|
231
|
-
label: 'Transverse Montage'
|
|
232
|
-
}],
|
|
233
|
-
selectedMontage: '',
|
|
234
|
-
playSpeedOptions: [{
|
|
235
|
-
value: 0.5,
|
|
236
|
-
label: '0.5x'
|
|
237
|
-
}, {
|
|
238
|
-
value: 1,
|
|
239
|
-
label: '1x'
|
|
240
|
-
}, {
|
|
241
|
-
value: 2,
|
|
242
|
-
label: '2x'
|
|
243
|
-
}, {
|
|
244
|
-
value: 5,
|
|
245
|
-
label: '5x'
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
value: 10,
|
|
249
|
-
label: '10x'
|
|
250
|
-
}],
|
|
251
|
-
selectedPlaySpeed: null,
|
|
252
|
-
intervalTimer: null,
|
|
253
|
-
intervalPeriod: 150,
|
|
254
|
-
intervalPage: 1000000
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
mounted: function () {
|
|
258
|
-
this.selectedMontage = 'NOT_MONTAGED'
|
|
259
|
-
this.selectedPlaySpeed = 1
|
|
260
|
-
},
|
|
261
|
-
methods: {
|
|
262
|
-
updateMontageScheme: function (value) {
|
|
263
|
-
console.log('Updating Montage Scheme:' + value)
|
|
264
|
-
this.$store.dispatch('setViewerMontageScheme', value)
|
|
265
|
-
},
|
|
266
|
-
updatePlaybackSpeed: function (value) {
|
|
267
|
-
console.log('Updating Playback Speed:' + value)
|
|
268
|
-
},
|
|
269
|
-
toggleTimeZoom: function () {
|
|
270
|
-
this.showTimeZoom = !this.showTimeZoom
|
|
271
|
-
},
|
|
272
|
-
toggleVerticalZoom: function () {
|
|
273
|
-
this.showVertZoom = !this.showVertZoom
|
|
274
|
-
},
|
|
275
|
-
togglePlaybackSpeed: function () {
|
|
276
|
-
this.showPlaybackSpeed = !this.showPlaybackSpeed
|
|
277
|
-
},
|
|
278
|
-
togglePlayback: function () {
|
|
279
|
-
if(this.isPlaying === false) {
|
|
280
|
-
this.startPlay();
|
|
281
|
-
} else {
|
|
282
|
-
this.stopPlay();
|
|
283
|
-
}
|
|
284
|
-
},
|
|
285
|
-
pageBack: function() {
|
|
286
|
-
this.$emit('pageBack')
|
|
287
|
-
},
|
|
288
|
-
pageForward: function() {
|
|
289
|
-
this.$emit('pageForward')
|
|
290
|
-
},
|
|
291
|
-
incrementZoom: function() {
|
|
292
|
-
this.$emit('incrementZoom')
|
|
293
|
-
},
|
|
294
|
-
decrementZoom: function() {
|
|
295
|
-
this.$emit('decrementZoom')
|
|
296
|
-
},
|
|
297
|
-
updateDuration: function() {
|
|
298
|
-
this.$emit('updateDuration',this.selectedTimeRange)
|
|
299
|
-
},
|
|
300
|
-
nextAnnotation: function () {
|
|
301
|
-
this.$emit('nextAnnotation')
|
|
302
|
-
},
|
|
303
|
-
previousAnnotation: function () {
|
|
304
|
-
this.$emit('previousAnnotation')
|
|
305
|
-
},
|
|
306
|
-
startPlay: function() {
|
|
307
|
-
this.isPlaying = true
|
|
308
|
-
let that = this;
|
|
309
|
-
this.intervalTimerFnc = function() {
|
|
310
|
-
that.$emit('setStart', that.start + (that.intervalPage * that.selectedPlaySpeed))
|
|
311
|
-
that.intervalTimer = setTimeout( that.intervalTimerFnc, that.intervalPeriod);
|
|
312
|
-
}
|
|
313
|
-
this.intervalTimer = setTimeout(this.intervalTimerFnc, this.intervalPeriod);
|
|
314
|
-
},
|
|
315
|
-
stopPlay: function() {
|
|
316
|
-
this.isPlaying = false
|
|
317
|
-
this.intervalPeriod = 150;
|
|
318
|
-
clearInterval(this.intervalTimer);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
</script>
|
|
323
|
-
|
|
324
|
-
<style lang="scss" scoped>
|
|
325
|
-
.timeseries-viewer-toolbar {
|
|
326
|
-
border-top: 1px solid #DADADA;
|
|
327
|
-
background: #F7F7F7;
|
|
328
|
-
display: flex;
|
|
329
|
-
padding: 8px 0;
|
|
330
|
-
width: 100%;
|
|
331
|
-
justify-content: space-between;
|
|
332
|
-
align-items: center;
|
|
333
|
-
}
|
|
334
|
-
.icon {
|
|
335
|
-
vertical-align: middle;
|
|
336
|
-
padding-bottom: 1px;
|
|
337
|
-
}
|
|
338
|
-
.btn-icon {
|
|
339
|
-
color: #928D85;
|
|
340
|
-
margin-left: 8px;
|
|
341
|
-
margin-right: 2px;
|
|
342
|
-
&:last-child {
|
|
343
|
-
margin-right:8px;
|
|
344
|
-
}
|
|
345
|
-
&.selected, &:hover, &[focused] {
|
|
346
|
-
color: #5039F7;
|
|
347
|
-
}
|
|
348
|
-
&[disabled] {
|
|
349
|
-
color: #E7E5E1;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
.playSelect {
|
|
353
|
-
width: 75px;
|
|
354
|
-
margin-right: 8px;
|
|
355
|
-
}
|
|
356
|
-
</style>
|
package/src/components/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import TSViewer from './TSViewer.vue'
|
|
2
|
-
import store from '../store'
|
|
3
|
-
export default {
|
|
4
|
-
install (Vue, options) {
|
|
5
|
-
if (!options || !options.store) {
|
|
6
|
-
throw new Error('Please initialise plugin with a Vuex store.')
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
options.store.registerModule('tsviewer', store)
|
|
10
|
-
|
|
11
|
-
Vue.component('ts-viewer', TSViewer)
|
|
12
|
-
}
|
|
13
|
-
}
|
package/src/main.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import Vue from 'vue'
|
|
2
|
-
import App from './App'
|
|
3
|
-
import store from '@/store/index.js'
|
|
4
|
-
import Vuex from 'vuex'
|
|
5
|
-
import SystemDesignComponents from '@nih-sparc/sparc-design-system-components'
|
|
6
|
-
import * as svgicon from 'vue-svgicon'
|
|
7
|
-
import '@/assets/icons/index.js'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Vue.use(Vuex)
|
|
11
|
-
Vue.use(SystemDesignComponents)
|
|
12
|
-
Vue.use(svgicon, {
|
|
13
|
-
tagName: 'svg-icon'
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
Vue.config.productionTip = false
|
|
17
|
-
|
|
18
|
-
new Vue({
|
|
19
|
-
el: '#app',
|
|
20
|
-
store: new Vuex.Store(store),
|
|
21
|
-
template: '<App/>',
|
|
22
|
-
components: { App }
|
|
23
|
-
})
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { prop, propOr } from 'ramda'
|
|
2
|
-
|
|
3
|
-
const _isString = x => Object.prototype.toString.call(x) === '[object String]'
|
|
4
|
-
|
|
5
|
-
const _trimValues = obj => {
|
|
6
|
-
Object.keys(obj).forEach(key => {
|
|
7
|
-
if (_isString(obj[key])) {
|
|
8
|
-
obj[key] = obj[key].trim()
|
|
9
|
-
}
|
|
10
|
-
})
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export default {
|
|
14
|
-
data() {
|
|
15
|
-
return {
|
|
16
|
-
method: 'GET',
|
|
17
|
-
body: null,
|
|
18
|
-
isLoading: true
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
methods: {
|
|
22
|
-
/**
|
|
23
|
-
* Sends an XHR request
|
|
24
|
-
* @param {Object} opts
|
|
25
|
-
* @returns {Promise}
|
|
26
|
-
*/
|
|
27
|
-
sendXhr: function(url, opts, returnRawResponse = false) {
|
|
28
|
-
if (!url) {
|
|
29
|
-
return Promise.reject(new Error('Url is missing!'))
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
this.isLoading = true
|
|
33
|
-
this.method = propOr('GET', 'method', opts)
|
|
34
|
-
|
|
35
|
-
const optsHeader = propOr(null, 'header', opts)
|
|
36
|
-
const headers = optsHeader || { 'Content-type': 'application/json' }
|
|
37
|
-
|
|
38
|
-
const optsBody = propOr('', 'body', opts)
|
|
39
|
-
let requestOpts = { headers, method: this.method }
|
|
40
|
-
|
|
41
|
-
if (optsBody) {
|
|
42
|
-
if (typeof optsBody === 'object') {
|
|
43
|
-
_trimValues(optsBody)
|
|
44
|
-
}
|
|
45
|
-
this.body = JSON.stringify(optsBody)
|
|
46
|
-
requestOpts = {
|
|
47
|
-
requestOpts,
|
|
48
|
-
body: this.body
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return fetch(url, requestOpts).then(resp => {
|
|
53
|
-
if (resp.status >= 400) {
|
|
54
|
-
return Promise.reject(resp)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// most common cases work processing the response as json, otherwise we have the option to parse per usecase
|
|
58
|
-
if (returnRawResponse) {
|
|
59
|
-
return this.finishLoading(resp)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// if the payload cannot be converted to json, return a clone of the original response
|
|
63
|
-
return resp
|
|
64
|
-
.json()
|
|
65
|
-
.then(this.finishLoading.bind(this))
|
|
66
|
-
.catch(() => this.finishLoading(resp))
|
|
67
|
-
})
|
|
68
|
-
},
|
|
69
|
-
/**
|
|
70
|
-
* Update isLoading on $nextTick
|
|
71
|
-
* @param {Object} json
|
|
72
|
-
* @returns {Object}
|
|
73
|
-
*/
|
|
74
|
-
finishLoading: function(json) {
|
|
75
|
-
this.$nextTick(() => {
|
|
76
|
-
this.isLoading = false
|
|
77
|
-
})
|
|
78
|
-
return json
|
|
79
|
-
},
|
|
80
|
-
/**
|
|
81
|
-
* Handles ajax errors
|
|
82
|
-
* @param {Object} err
|
|
83
|
-
*/
|
|
84
|
-
handleXhrError: function(err) {
|
|
85
|
-
this.isLoading = false
|
|
86
|
-
const status = prop('status', err)
|
|
87
|
-
// logout
|
|
88
|
-
if (status === 401) {
|
|
89
|
-
return this.handleLogout()
|
|
90
|
-
}
|
|
91
|
-
// unauthorized
|
|
92
|
-
if (status === 403) {
|
|
93
|
-
console.error('unauthorized')
|
|
94
|
-
// return this.$router.replace({name: 'datasets-list'})
|
|
95
|
-
}
|
|
96
|
-
// emit ajaxError
|
|
97
|
-
this.$emit('ajaxError', err)
|
|
98
|
-
},
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import Request from '@/mixins/request'
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
mixins: [
|
|
5
|
-
Request
|
|
6
|
-
],
|
|
7
|
-
|
|
8
|
-
computed: {
|
|
9
|
-
activeViewer: function() {
|
|
10
|
-
return this.$store.getters.activeViewer
|
|
11
|
-
},
|
|
12
|
-
viewerChannels: function() {
|
|
13
|
-
return this.$store.getters.viewerChannels
|
|
14
|
-
},
|
|
15
|
-
viewerAnnotations: function() {
|
|
16
|
-
return this.$store.getters.viewerAnnotations
|
|
17
|
-
},
|
|
18
|
-
viewerSidePanelOpen: function() {
|
|
19
|
-
return this.$store.getters.viewerSidePanelOpen
|
|
20
|
-
},
|
|
21
|
-
activeAnnotation: function() {
|
|
22
|
-
return this.$store.getters.activeAnnotation
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
methods: {
|
|
27
|
-
addAnnotation: function() {
|
|
28
|
-
|
|
29
|
-
// assert that we only call this function on activeAnnotations without an existing ID
|
|
30
|
-
if (this.activeAnnotation.id) {
|
|
31
|
-
throw new TypeError("Trying to create an annotation that already exists", this.activeAnnotation.id)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
let start = this.activeAnnotation.start
|
|
35
|
-
let duration = this.activeAnnotation.duration
|
|
36
|
-
const onAll = this.activeAnnotation.allChannels
|
|
37
|
-
const label = this.activeAnnotation.label
|
|
38
|
-
const description = this.activeAnnotation.description
|
|
39
|
-
const layer_id = this.activeAnnotation.layer_id
|
|
40
|
-
|
|
41
|
-
// correct negative durations
|
|
42
|
-
if (duration < 0 ) {
|
|
43
|
-
duration = -duration;
|
|
44
|
-
start = start - duration;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const onChannels = [];
|
|
48
|
-
for (let ch = 0; ch < this.viewerChannels.length; ch++) {
|
|
49
|
-
const curChannelView = this.viewerChannels[ch];
|
|
50
|
-
if((curChannelView.selected && curChannelView.visible) || onAll) {
|
|
51
|
-
const id = this.getChannelId(curChannelView)
|
|
52
|
-
onChannels.push(id);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const XhrBody = {
|
|
57
|
-
name: '',
|
|
58
|
-
channelIds: onChannels,
|
|
59
|
-
label: label,
|
|
60
|
-
description: description,
|
|
61
|
-
layer_id: layer_id,
|
|
62
|
-
start: start,
|
|
63
|
-
end: start + duration
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
//Unselect current annotations
|
|
67
|
-
// this.unSelectAnnotations(null, false);
|
|
68
|
-
|
|
69
|
-
// Send ADD annotation request to server
|
|
70
|
-
const timeseriesId = this.activeViewer.content.nodeId
|
|
71
|
-
const url = `${this.config.apiUrl}/timeseries/${timeseriesId}/layers/${layer_id}/annotations`
|
|
72
|
-
this.sendXhr(url, {
|
|
73
|
-
method:'POST',
|
|
74
|
-
header: {
|
|
75
|
-
'Authorization': `Bearer ${this.$store.state.userToken}`
|
|
76
|
-
},
|
|
77
|
-
body:XhrBody
|
|
78
|
-
} ).then((response) => {
|
|
79
|
-
const newAnn = {
|
|
80
|
-
name: '',
|
|
81
|
-
id: response.id,
|
|
82
|
-
label: response.label,
|
|
83
|
-
description: response.description,
|
|
84
|
-
start: response.start,
|
|
85
|
-
duration: response.end - response.start,
|
|
86
|
-
end: response.end,
|
|
87
|
-
cStart: null,
|
|
88
|
-
cEnd: null,
|
|
89
|
-
selected: true,
|
|
90
|
-
channelIds: response.channelIds,
|
|
91
|
-
allChannels: false,
|
|
92
|
-
layer_id: response.layerId,
|
|
93
|
-
userId: response.userId
|
|
94
|
-
};
|
|
95
|
-
if (response.linkedPackage) {
|
|
96
|
-
newAnn.linkedPackage = response.linkedPackage
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Check if all channels are selected
|
|
100
|
-
if (newAnn.channelIds.length >= this.viewerChannels.length) {
|
|
101
|
-
newAnn.allChannels = true;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Find layer
|
|
105
|
-
let curLIndex = 0;
|
|
106
|
-
for (let i = 0; i < this.viewerAnnotations.length; i++) {
|
|
107
|
-
if (this.viewerAnnotations[i].id === response.layerId) {
|
|
108
|
-
curLIndex = i;
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
this.$store.dispatch('createAnnotation', newAnn)
|
|
114
|
-
.then(() => {
|
|
115
|
-
this.sortAnns(this.viewerAnnotations[curLIndex].annotations);
|
|
116
|
-
this.onAnnotationCreated()
|
|
117
|
-
}).catch(error => {
|
|
118
|
-
console.log(error)
|
|
119
|
-
})
|
|
120
|
-
}).catch(error => {
|
|
121
|
-
console.log(error)
|
|
122
|
-
})
|
|
123
|
-
},
|
|
124
|
-
updateAnnotation: function() {
|
|
125
|
-
|
|
126
|
-
if (!this.activeAnnotation.id) {
|
|
127
|
-
throw new TypeError("Trying to update an annotation that doesn't exists on server", this.activeAnnotation.id)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
let start = this.activeAnnotation.start
|
|
131
|
-
let duration = this.activeAnnotation.duration
|
|
132
|
-
|
|
133
|
-
// correct negative durations
|
|
134
|
-
if (duration < 0 ) {
|
|
135
|
-
duration = -duration;
|
|
136
|
-
start = start - duration;
|
|
137
|
-
this.activeAnnotation.start = start
|
|
138
|
-
this.activeAnnotation.duration = duration
|
|
139
|
-
this.activeAnnotation.end = start + duration
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const annLayerId = this.activeAnnotation.layer_id
|
|
143
|
-
const timeseriesId = this.activeViewer.content.nodeId
|
|
144
|
-
const url = `${this.config.apiUrl}/timeseries/${timeseriesId}/layers/${annLayerId}/annotations/${this.activeAnnotation.id}`;
|
|
145
|
-
|
|
146
|
-
const XhrBody = {
|
|
147
|
-
name: '',
|
|
148
|
-
channelIds: this.activeAnnotation.channelIds,
|
|
149
|
-
label: this.activeAnnotation.label,
|
|
150
|
-
description: this.activeAnnotation.description,
|
|
151
|
-
layer_id: this.activeAnnotation.layer_id,
|
|
152
|
-
start: start,
|
|
153
|
-
end: start + duration
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const self = this
|
|
157
|
-
self.sendXhr(url, {
|
|
158
|
-
method:'PUT',
|
|
159
|
-
header: {
|
|
160
|
-
'Authorization': `Bearer ${this.$store.state.userToken}`
|
|
161
|
-
},
|
|
162
|
-
body:XhrBody
|
|
163
|
-
} ).then(() => {
|
|
164
|
-
self.$store.dispatch('updateAnnotation', this.activeAnnotation)
|
|
165
|
-
self.onAnnotationUpdated()
|
|
166
|
-
})
|
|
167
|
-
.catch(self.handleXhrError.bind(this))
|
|
168
|
-
},
|
|
169
|
-
removeAnnotation: function(annotation) {
|
|
170
|
-
let annLayerId = ''
|
|
171
|
-
// annotation data structure properties vary depending on if the user
|
|
172
|
-
// is canceling newly created annotation or not
|
|
173
|
-
if (annotation.layer) {
|
|
174
|
-
annLayerId = annotation.layer.id
|
|
175
|
-
} else {
|
|
176
|
-
annLayerId = annotation.layer_id
|
|
177
|
-
}
|
|
178
|
-
const timeseriesId = this.activeViewer.content.nodeId
|
|
179
|
-
const url = `${this.config.apiUrl}/timeseries/${timeseriesId}/layers/${annLayerId}/annotations/${annotation.id}`;
|
|
180
|
-
|
|
181
|
-
const self = this
|
|
182
|
-
self.sendXhr(url, {
|
|
183
|
-
method:'DELETE',
|
|
184
|
-
header: {
|
|
185
|
-
'Authorization': `Bearer ${this.$store.state.userToken}`
|
|
186
|
-
},
|
|
187
|
-
} ).then(() => {
|
|
188
|
-
self.$store.dispatch('deleteAnnotation', annotation)
|
|
189
|
-
self.onAnnotationDeleted()
|
|
190
|
-
})
|
|
191
|
-
.catch(self.handleXhrError.bind(this))
|
|
192
|
-
|
|
193
|
-
},
|
|
194
|
-
sortAnns: function(annArray) {
|
|
195
|
-
annArray.sort(function Comparator(a, b) {
|
|
196
|
-
if (a.start < b.start) return -1;
|
|
197
|
-
if (a.start > b.start) return 1;
|
|
198
|
-
return 0;
|
|
199
|
-
});
|
|
200
|
-
},
|
|
201
|
-
}
|
|
202
|
-
}
|