tsviewer 0.1.0 → 1.0.3

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.
Files changed (37) hide show
  1. package/README.md +9 -0
  2. package/dist/tsviewer.css +1 -0
  3. package/dist/tsviewer.es.js +21456 -0
  4. package/dist/tsviewer.umd.js +26 -33259
  5. package/package.json +35 -32
  6. package/babel.config.js +0 -5
  7. package/dist/demo.html +0 -1
  8. package/dist/tsviewer.common.js +0 -33247
  9. package/dist/tsviewer.common.js.map +0 -1
  10. package/dist/tsviewer.umd.js.map +0 -1
  11. package/dist/tsviewer.umd.min.js +0 -4
  12. package/dist/tsviewer.umd.min.js.map +0 -1
  13. package/jsconfig.json +0 -19
  14. package/public/favicon.ico +0 -0
  15. package/public/index.html +0 -17
  16. package/src/App.vue +0 -41
  17. package/src/assets/icons/blackfynn-amplitude-zoom.js +0 -11
  18. package/src/assets/icons/blackfynn-timescale.js +0 -11
  19. package/src/assets/icons/icon-controller-pause.js +0 -11
  20. package/src/assets/icons/icon-controller-play.js +0 -11
  21. package/src/assets/icons/icon-next-page.js +0 -11
  22. package/src/assets/icons/icon-previous-page.js +0 -11
  23. package/src/assets/icons/icon-stopwatch.js +0 -11
  24. package/src/assets/icons/index.js +0 -7
  25. package/src/components/TSPlotCanvas.vue +0 -1868
  26. package/src/components/TSScrubber.vue +0 -420
  27. package/src/components/TSViewer.vue +0 -595
  28. package/src/components/TSViewerCanvas.vue +0 -793
  29. package/src/components/TSViewerToolbar.vue +0 -356
  30. package/src/components/index.js +0 -13
  31. package/src/main.js +0 -23
  32. package/src/mixins/request/index.js +0 -100
  33. package/src/mixins/ts-annotation/index.js +0 -202
  34. package/src/mixins/viewer-active-tool/index.js +0 -36
  35. package/src/store/index.js +0 -184
  36. package/src/utils/constants.js +0 -15
  37. 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>
@@ -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
- }