@insync-stageplayer/plotly-chart 0.5.27 → 0.5.35-beta.1
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/lib/PlotlyGraph/EventMenu.d.ts +13 -0
- package/lib/PlotlyGraph/EventMenu.d.ts.map +1 -0
- package/lib/PlotlyGraph/EventMenu.js +84 -0
- package/lib/PlotlyGraph/EventMenu.js.map +1 -0
- package/lib/PlotlyGraph/MarkerTracks.d.ts +17 -0
- package/lib/PlotlyGraph/MarkerTracks.d.ts.map +1 -0
- package/lib/PlotlyGraph/MarkerTracks.js +248 -0
- package/lib/PlotlyGraph/MarkerTracks.js.map +1 -0
- package/lib/PlotlyGraph/PlotlyLiveview.d.ts +4 -4
- package/lib/PlotlyGraph/PlotlyLiveview.js +297 -297
- package/lib/PlotlyGraph/PlotlyPlayback.d.ts +4 -4
- package/lib/PlotlyGraph/PlotlyPlayback.d.ts.map +1 -1
- package/lib/PlotlyGraph/PlotlyPlayback.js +524 -317
- package/lib/PlotlyGraph/PlotlyPlayback.js.map +1 -1
- package/lib/PlotlyGraph/PlotlyPlaybackOverlay.d.ts +23 -0
- package/lib/PlotlyGraph/PlotlyPlaybackOverlay.d.ts.map +1 -0
- package/lib/PlotlyGraph/PlotlyPlaybackOverlay.js +188 -0
- package/lib/PlotlyGraph/PlotlyPlaybackOverlay.js.map +1 -0
- package/lib/PlotlyGraph/index.d.ts +2 -2
- package/lib/PlotlyGraph/index.d.ts.map +1 -1
- package/lib/PlotlyGraph/index.js +2 -2
- package/lib/PlotlyGraph/index.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/package.json +5 -3
- package/lib/Plotly.d.ts +0 -5
- package/lib/Plotly.d.ts.map +0 -1
- package/lib/Plotly.js +0 -338
- package/lib/Plotly.js.map +0 -1
- package/lib/PlotlyGraph/Plotly.d.ts +0 -5
- package/lib/PlotlyGraph/Plotly.d.ts.map +0 -1
- package/lib/PlotlyGraph/Plotly.js +0 -347
- package/lib/PlotlyGraph/Plotly.js.map +0 -1
- package/lib/PlotlyLiveview.d.ts +0 -5
- package/lib/PlotlyLiveview.d.ts.map +0 -1
- package/lib/PlotlyLiveview.js +0 -310
- package/lib/PlotlyLiveview.js.map +0 -1
|
@@ -1,28 +1,48 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useState } from "react";
|
|
2
|
-
import Plot from "react-plotly.js";
|
|
3
|
-
import PropTypes from "prop-types";
|
|
4
|
-
import { withResizeDetector } from "react-resize-detector";
|
|
5
|
-
import { useTheme as useSelectedTheme, styled, } from "@insync-stageplayer/ui-components";
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
import React, { useCallback, useEffect, useState, useRef } from "react";
|
|
2
|
+
import Plot from "react-plotly.js";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { withResizeDetector } from "react-resize-detector";
|
|
5
|
+
import { useTheme as useSelectedTheme, styled, } from "@insync-stageplayer/ui-components";
|
|
6
|
+
const normalizeRange = 1000;
|
|
7
|
+
const convertMicrosecondstoDateFormat = (inputMicroseconds) => {
|
|
8
|
+
let convertedDate = new Date(+inputMicroseconds / 1000);
|
|
9
|
+
return adjustWithLocalTimeZone(convertedDate);
|
|
10
|
+
};
|
|
11
|
+
const adjustWithLocalTimeZone = (date) => {
|
|
12
|
+
let adjustedDate = new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000);
|
|
13
|
+
return adjustedDate;
|
|
14
|
+
};
|
|
15
|
+
const convertDateToMicroseconds = (inputDate) => {
|
|
16
|
+
const convertIntoDate = new Date(inputDate);
|
|
17
|
+
return (convertIntoDate.getTime() * 1000 -
|
|
18
|
+
convertIntoDate.getTimezoneOffset() * 60 * 1000 * 1000);
|
|
19
|
+
};
|
|
20
|
+
const getMicroSecondStartAndLength = (originalFromDate, originalStopDate, totalTime) => {
|
|
21
|
+
const start = convertDateToMicroseconds(originalFromDate);
|
|
22
|
+
const end = convertDateToMicroseconds(originalStopDate);
|
|
23
|
+
let sLength = end - start;
|
|
24
|
+
const length = sLength + (totalTime % 1000) === totalTime ? totalTime : sLength;
|
|
25
|
+
return [start, length];
|
|
26
|
+
};
|
|
27
|
+
const convertMicrosecondsToDate = (inputTime) => {
|
|
28
|
+
const date = new Date(inputTime / 1000 - 3600 * 1000);
|
|
29
|
+
const pad = function (num) {
|
|
30
|
+
return (num < 10 ? "0" : "") + num;
|
|
31
|
+
};
|
|
32
|
+
return (date.getFullYear() +
|
|
33
|
+
"-" +
|
|
34
|
+
pad(date.getMonth() + 1) +
|
|
35
|
+
"-" +
|
|
36
|
+
pad(date.getDate()) +
|
|
37
|
+
" " +
|
|
38
|
+
pad(date.getHours()) +
|
|
39
|
+
":" +
|
|
40
|
+
pad(date.getMinutes()) +
|
|
41
|
+
":" +
|
|
42
|
+
pad(date.getSeconds()) +
|
|
43
|
+
"." +
|
|
44
|
+
pad(date.getMilliseconds()));
|
|
45
|
+
};
|
|
26
46
|
const StyledPlotly = styled(Plot) `
|
|
27
47
|
rect.nsewdrag.cursor-ew-resize {
|
|
28
48
|
cursor: zoom-in;
|
|
@@ -35,296 +55,483 @@ const StyledPlotly = styled(Plot) `
|
|
|
35
55
|
cursor: grab;
|
|
36
56
|
pointer-events: none !important;
|
|
37
57
|
}
|
|
38
|
-
`;
|
|
39
|
-
export const PlotlyPlayback = withResizeDetector(({ xRange, data, metadata, onStopSelect, onDrag, xScaleTickFormat, scrubbing, yAxisLabel, displaySecondYAxis, displayArrow, totalTime, }) => {
|
|
40
|
-
var _a;
|
|
41
|
-
const [plotData, setPlotData] = useState([]);
|
|
42
|
-
const [nowLine, setNowline] = useState((_a = sessionStorage.getItem("nl")) !== null && _a !== void 0 ? _a : 0);
|
|
43
|
-
const [layout, setLayout] = useState(null);
|
|
44
|
-
const selectedTheme = useSelectedTheme();
|
|
45
|
-
const [yAxisLabelLeft, setYAxisLabelLeft] = useState("");
|
|
46
|
-
const [yAxisLabelRight, setYAxisLabelRight] = useState("");
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
anchor: "
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
data
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
metadata
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
58
|
+
`;
|
|
59
|
+
export const PlotlyPlayback = withResizeDetector(({ xRange, data, metadata, onStopSelect, onDrag, xScaleTickFormat, scrubbing, yAxisLabel, displaySecondYAxis, displayArrow, totalTime, startPositionCurrentTimeIndicator, onRenderedWidth, onRenderedLeft, onRenderedTop, onRenderedHeight, onRenderedScrubbar, percentageHeight, }) => {
|
|
60
|
+
var _a;
|
|
61
|
+
const [plotData, setPlotData] = useState([]);
|
|
62
|
+
const [nowLine, setNowline] = useState((_a = sessionStorage.getItem("nl")) !== null && _a !== void 0 ? _a : 0);
|
|
63
|
+
const [layout, setLayout] = useState(null);
|
|
64
|
+
const selectedTheme = useSelectedTheme();
|
|
65
|
+
const [yAxisLabelLeft, setYAxisLabelLeft] = useState("");
|
|
66
|
+
const [yAxisLabelRight, setYAxisLabelRight] = useState("");
|
|
67
|
+
const [yAxisLabelLeftColor, setYAxisLabelLeftColor] = useState("");
|
|
68
|
+
const [yAxisLabelRightColor, setYAxisLabelRightColor] = useState("");
|
|
69
|
+
const plotlyRef = useRef();
|
|
70
|
+
const updateLayout = useCallback(() => {
|
|
71
|
+
// let plotlytimeindicator = [
|
|
72
|
+
const nowline_color = "rgba(255, 0, 0, 1)";
|
|
73
|
+
const annotations = [
|
|
74
|
+
{
|
|
75
|
+
xref: "paper",
|
|
76
|
+
yref: "paper",
|
|
77
|
+
x: nowLine,
|
|
78
|
+
xanchor: "right",
|
|
79
|
+
y: 1,
|
|
80
|
+
yanchor: "bottom",
|
|
81
|
+
text: "",
|
|
82
|
+
showarrow: displayArrow,
|
|
83
|
+
arrowhead: 0,
|
|
84
|
+
ax: 0,
|
|
85
|
+
ay: 4000,
|
|
86
|
+
arrowcolor: nowline_color,
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
const shapes = [
|
|
90
|
+
{
|
|
91
|
+
type: "rect",
|
|
92
|
+
xref: "paper",
|
|
93
|
+
yref: "paper",
|
|
94
|
+
layer: "below",
|
|
95
|
+
x0: 0,
|
|
96
|
+
y0: 0,
|
|
97
|
+
x1: 1,
|
|
98
|
+
y1: -0.19,
|
|
99
|
+
fillcolor: selectedTheme.colors.scrubBarColor,
|
|
100
|
+
line: {
|
|
101
|
+
color: selectedTheme.colors.scrubBarColor,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
const convertXRangeFrom = xScaleTickFormat.includes(":")
|
|
106
|
+
? convertMicrosecondstoDateFormat(xRange.from > 0 || selectedTheme.name !== "noldus"
|
|
107
|
+
? xRange.length === totalTime
|
|
108
|
+
? xRange.from
|
|
109
|
+
: xRange.from + xRange.length > totalTime &&
|
|
110
|
+
selectedTheme.name === "noldus"
|
|
111
|
+
? totalTime - xRange.length
|
|
112
|
+
: xRange.from
|
|
113
|
+
: 0)
|
|
114
|
+
: xRange.from / 1e6;
|
|
115
|
+
const convertXRangeTo = xScaleTickFormat.includes(":")
|
|
116
|
+
? convertMicrosecondstoDateFormat(xRange.from > 0 || selectedTheme.name !== "noldus"
|
|
117
|
+
? xRange.length === totalTime
|
|
118
|
+
? xRange.length + xRange.from
|
|
119
|
+
: xRange.from + xRange.length > totalTime &&
|
|
120
|
+
selectedTheme.name === "noldus"
|
|
121
|
+
? totalTime
|
|
122
|
+
: xRange.from + xRange.length
|
|
123
|
+
: xRange.length)
|
|
124
|
+
: (xRange.from + xRange.length) / 1e6;
|
|
125
|
+
const minY = yScaleRange[0].min;
|
|
126
|
+
const maxY = yScaleRange[0].max;
|
|
127
|
+
// only add y label when set, otherwise will give a lot of extra margin
|
|
128
|
+
const yAxisWithLabel = yAxisLabel && yAxisLabelLeft !== ""
|
|
129
|
+
? {
|
|
130
|
+
title: yAxisLabelLeft,
|
|
131
|
+
automargin: "width",
|
|
132
|
+
titlefont: {
|
|
133
|
+
color: yAxisLabelLeftColor,
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
: {
|
|
137
|
+
// a bit of margin for the y axis otherwise
|
|
138
|
+
anchor: "free",
|
|
139
|
+
shift: 5,
|
|
140
|
+
};
|
|
141
|
+
const sharedYaxis = Object.assign(Object.assign({}, yAxisWithLabel), { fixedrange: true, rangemode: "", showline: true, showticklabels: selectedTheme.name === "noldus" ? false : true, linewidth: 2, linecolor: selectedTheme.colors.accent, tickformat: null });
|
|
142
|
+
// Noldus doesn't need the precision, where MARIN wants it to be as precise as possible
|
|
143
|
+
// MARIN wants it's own normalization when working with different units (e.g kn and m)
|
|
144
|
+
const yAxis = selectedTheme.name === "noldus"
|
|
145
|
+
? Object.assign(Object.assign({}, sharedYaxis), { hoverformat: ".2f" }) : Object.assign(Object.assign({}, sharedYaxis), { range: [minY, maxY], showline: shouldNormalize ? false : true, showticklabels: shouldNormalize ? false : true });
|
|
146
|
+
let defaultLayout = {
|
|
147
|
+
// this hovermode setting creates a hover-over legend for all the signals at the same time. It also adds a spike line
|
|
148
|
+
hovermode: "x unified",
|
|
149
|
+
yaxis: yAxis,
|
|
150
|
+
xaxis: {
|
|
151
|
+
rangemode: "",
|
|
152
|
+
showline: true,
|
|
153
|
+
linewidth: 2,
|
|
154
|
+
linecolor: selectedTheme.colors.accent,
|
|
155
|
+
fixedrange: false,
|
|
156
|
+
range: [convertXRangeFrom, convertXRangeTo],
|
|
157
|
+
tickformat: xScaleTickFormat.includes(":") ? "%H:%M:%S" : null,
|
|
158
|
+
// dtick: 5, // removing this allows for automatic per zoom level
|
|
159
|
+
ticks: "outside top",
|
|
160
|
+
ticklen: 15,
|
|
161
|
+
tickcolor: selectedTheme.colors.dtickColor,
|
|
162
|
+
ticklabelposition: "inside",
|
|
163
|
+
minor: {
|
|
164
|
+
ticks: "inside top",
|
|
165
|
+
ticklen: 9,
|
|
166
|
+
tickmode: "auto",
|
|
167
|
+
nticks: 10,
|
|
168
|
+
tickcolor: selectedTheme.colors.dtickMinorColor,
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
showlegend: false,
|
|
172
|
+
autosize: true,
|
|
173
|
+
margin: { l: 25, r: 10, t: 20, b: 20 },
|
|
174
|
+
paper_bgcolor: selectedTheme.colors.background,
|
|
175
|
+
plot_bgcolor: selectedTheme.colors.background,
|
|
176
|
+
font: { color: selectedTheme.colors.foreground },
|
|
177
|
+
};
|
|
178
|
+
// only add y label when set, setting it empty otherwise will give extra margin
|
|
179
|
+
const yAxis2WithLabel = yAxisLabel && yAxisLabelRight !== ""
|
|
180
|
+
? {
|
|
181
|
+
title: yAxisLabelRight,
|
|
182
|
+
titlefont: {
|
|
183
|
+
color: yAxisLabelRightColor,
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
: {};
|
|
187
|
+
// Check if a second y-axis needs to be added
|
|
188
|
+
if (displaySecondYAxis && metadata.length == 2) {
|
|
189
|
+
const yAxis2 = Object.assign(Object.assign({}, yAxis2WithLabel), { fixedrange: true, range: [yScaleRange[1].min, yScaleRange[1].max], anchor: "x", overlaying: "y", side: "right", automargin: "width" });
|
|
190
|
+
defaultLayout = Object.assign(Object.assign({}, defaultLayout), { yaxis2: yAxis2 });
|
|
191
|
+
}
|
|
192
|
+
// when scrubbing plotly is in charge, this to prevent the xRange to update and mess while
|
|
193
|
+
// still scrubbing in plotly
|
|
194
|
+
if (!scrubbing) {
|
|
195
|
+
setLayout(Object.assign(Object.assign({}, defaultLayout), { shapes, annotations }));
|
|
196
|
+
}
|
|
197
|
+
}, [
|
|
198
|
+
selectedTheme,
|
|
199
|
+
xRange,
|
|
200
|
+
xScaleTickFormat,
|
|
201
|
+
yAxisLabel,
|
|
202
|
+
yAxisLabelLeft,
|
|
203
|
+
yAxisLabelRight,
|
|
204
|
+
displaySecondYAxis,
|
|
205
|
+
displayArrow,
|
|
206
|
+
scrubbing,
|
|
207
|
+
metadata,
|
|
208
|
+
nowLine,
|
|
209
|
+
totalTime,
|
|
210
|
+
yAxisLabelLeftColor,
|
|
211
|
+
yAxisLabelRightColor,
|
|
212
|
+
]);
|
|
213
|
+
const onRelayout = (e) => {
|
|
214
|
+
if (e["xaxis.range[0]"] && e["xaxis.range[1]"]) {
|
|
215
|
+
let selection;
|
|
216
|
+
if (xScaleTickFormat.includes(":")) {
|
|
217
|
+
const [from, length] = getMicroSecondStartAndLength(e["xaxis.range[0]"], e["xaxis.range[1]"], totalTime);
|
|
218
|
+
selection = {
|
|
219
|
+
from: from,
|
|
220
|
+
length: length,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
selection = {
|
|
225
|
+
from: e["xaxis.range[0]"] * 1e6,
|
|
226
|
+
length: (e["xaxis.range[1]"] - e["xaxis.range[0]"]) * 1e6,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
if (selectedTheme.name === "noldus") {
|
|
230
|
+
const [from, length] = getMicroSecondStartAndLength(e["xaxis.range[0]"], e["xaxis.range[1]"], totalTime);
|
|
231
|
+
// fix if we go below zero time
|
|
232
|
+
if (selection.from < 0) {
|
|
233
|
+
selection.from = 0; // daniel fix 3 mar 2025
|
|
234
|
+
sessionStorage.setItem("startSelection", 0);
|
|
235
|
+
sessionStorage.setItem("endSelection", (e["xaxis.range[1]"] - e["xaxis.range[0]"]) * 1e6); // no date format error?
|
|
236
|
+
}
|
|
237
|
+
// fix if we go over end time
|
|
238
|
+
// console.log("DANIEL 1 totaltime="+totalTime+" RE="+e["xaxis.range[1]"]+" NL="+(from+length));
|
|
239
|
+
if (from + length > totalTime) {
|
|
240
|
+
var newenddate = convertMicrosecondsToDate(totalTime);
|
|
241
|
+
var newstartdate = convertMicrosecondsToDate(totalTime - length);
|
|
242
|
+
//console.log("DANIEL 3 out of range fix new start="+newstartdate+" new end="+newenddate+" len="+length);
|
|
243
|
+
sessionStorage.setItem("endSelection", newenddate);
|
|
244
|
+
sessionStorage.setItem("startSelection", newstartdate);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
onStopSelect({ selection });
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const onRelayouting = (e) => {
|
|
251
|
+
if (e["xaxis.range[0]"] && e["xaxis.range[1]"]) {
|
|
252
|
+
let seekTime;
|
|
253
|
+
if (xScaleTickFormat.includes(":")) {
|
|
254
|
+
const [from, length] = getMicroSecondStartAndLength(e["xaxis.range[0]"], e["xaxis.range[1]"], totalTime);
|
|
255
|
+
if (startPositionCurrentTimeIndicator === "0") {
|
|
256
|
+
if (selectedTheme.name === "noldus") {
|
|
257
|
+
// noldus below zero fix
|
|
258
|
+
if (from < 0) {
|
|
259
|
+
// daniel fix 19feb2025
|
|
260
|
+
sessionStorage.setItem("startSelection", convertMicrosecondsToDate(0));
|
|
261
|
+
sessionStorage.setItem("endSelection", convertMicrosecondsToDate(length));
|
|
262
|
+
onDrag(0);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
sessionStorage.setItem("startSelection", convertMicrosecondsToDate(from));
|
|
266
|
+
sessionStorage.setItem("endSelection", convertMicrosecondsToDate(from + length));
|
|
267
|
+
onDrag(from);
|
|
268
|
+
}
|
|
269
|
+
// noldus out of end range fix
|
|
270
|
+
if (from + length > totalTime) {
|
|
271
|
+
sessionStorage.setItem("endSelection", convertMicrosecondsToDate(totalTime));
|
|
272
|
+
sessionStorage.setItem("startSelection", convertMicrosecondsToDate(totalTime - length));
|
|
273
|
+
//onDrag(totalTime-length);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
const possibleSeekTime = length * nowLine + from;
|
|
279
|
+
seekTime =
|
|
280
|
+
possibleSeekTime > totalTime
|
|
281
|
+
? totalTime
|
|
282
|
+
: possibleSeekTime < 0
|
|
283
|
+
? 0
|
|
284
|
+
: possibleSeekTime;
|
|
285
|
+
sessionStorage.setItem("startSelection", from); // is this correct for marin should not also be date format?
|
|
286
|
+
sessionStorage.setItem("endSelection", length); // is this correct for marin should not also be date format, length wrong?
|
|
287
|
+
onDrag(seekTime);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
// set on drag
|
|
292
|
+
if (startPositionCurrentTimeIndicator === "0") {
|
|
293
|
+
seekTime = e["xaxis.range[0]"] * 1e6;
|
|
294
|
+
sessionStorage.setItem("startSelection", e["xaxis.range[0]"] * 1e6);
|
|
295
|
+
sessionStorage.setItem("endSelection", e["xaxis.range[1]"] * 1e6);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
seekTime =
|
|
299
|
+
((e["xaxis.range[1]"] - e["xaxis.range[0]"]) / 2 +
|
|
300
|
+
e["xaxis.range[0]"]) *
|
|
301
|
+
1e6;
|
|
302
|
+
sessionStorage.setItem("startSelection", e["xaxis.range[0]"] * 1e6);
|
|
303
|
+
sessionStorage.setItem("endSelection", e["xaxis.range[1]"] * 1e6);
|
|
304
|
+
}
|
|
305
|
+
onDrag(seekTime);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
// MARIN data should be normalized if the unit of the different signals are not the same
|
|
310
|
+
const shouldNormalize = React.useMemo(() => {
|
|
311
|
+
const units = metadata.reduce((acc, curr) => {
|
|
312
|
+
if (acc.indexOf(curr.unit) < 0) {
|
|
313
|
+
return [...acc, curr.unit];
|
|
314
|
+
}
|
|
315
|
+
return acc;
|
|
316
|
+
}, []);
|
|
317
|
+
return displaySecondYAxis ? units.length > 2 : units.length > 1;
|
|
318
|
+
}, [metadata, displaySecondYAxis]);
|
|
319
|
+
// Getting the range for the y-axis
|
|
320
|
+
const yScaleRange = React.useMemo(() => {
|
|
321
|
+
if (!shouldNormalize && metadata) {
|
|
322
|
+
if (displaySecondYAxis && metadata.length == 2) {
|
|
323
|
+
return [
|
|
324
|
+
{ min: metadata[0].min, max: metadata[0].max },
|
|
325
|
+
{ min: metadata[1].min, max: metadata[1].max },
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
const min = metadata.reduce((acc, l) => Math.min(acc, l.min), Infinity);
|
|
330
|
+
const max = metadata.reduce((acc, l) => Math.max(acc, l.max), -Infinity);
|
|
331
|
+
return [{ min, max }];
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return [{ min: 0, max: 1 }];
|
|
335
|
+
}, [shouldNormalize, metadata, displaySecondYAxis]);
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
const plotDataArr = [];
|
|
338
|
+
data.forEach((signal, idx) => {
|
|
339
|
+
// For Noldus we need to filter out the x from the objects, MARIN directly returns a Plotly optimized format
|
|
340
|
+
const x = selectedTheme.name === "noldus"
|
|
341
|
+
? signal.map((item) => {
|
|
342
|
+
if (xScaleTickFormat.includes(":")) {
|
|
343
|
+
const xDateFormatted = convertMicrosecondstoDateFormat(+item.x);
|
|
344
|
+
return xDateFormatted;
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
const xValue = +item.x / 1e6;
|
|
348
|
+
return xValue;
|
|
349
|
+
}
|
|
350
|
+
})
|
|
351
|
+
: signal[0].map((item) => {
|
|
352
|
+
if (xScaleTickFormat.includes(":")) {
|
|
353
|
+
const xDateFormatted = convertMicrosecondstoDateFormat(+item);
|
|
354
|
+
return xDateFormatted;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
const xValue = +item / 1e6;
|
|
358
|
+
return xValue;
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
// For Noldus we need to filter out the y from the objects, MARIN directly returns a Plotly optimized format
|
|
362
|
+
const yVal = selectedTheme.name === "noldus"
|
|
363
|
+
? signal.map((item) => {
|
|
364
|
+
return item.y;
|
|
365
|
+
})
|
|
366
|
+
: signal[1];
|
|
367
|
+
const y = handleYValue(yVal, idx);
|
|
368
|
+
const sharedSignalData = {
|
|
369
|
+
x,
|
|
370
|
+
y,
|
|
371
|
+
type: "scattergl",
|
|
372
|
+
mode: metadata[idx].frequency * (xRange.length / 1000 / 1000) > 250
|
|
373
|
+
? "lines"
|
|
374
|
+
: "lines+markers",
|
|
375
|
+
name: metadata[idx].name,
|
|
376
|
+
marker: {
|
|
377
|
+
color: metadata[idx].color,
|
|
378
|
+
size: 5,
|
|
379
|
+
line: {
|
|
380
|
+
color: metadata[idx].color,
|
|
381
|
+
width: 1,
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
const signalData = getSignalData(sharedSignalData, yVal);
|
|
386
|
+
plotDataArr.push(signalData);
|
|
387
|
+
});
|
|
388
|
+
// Check if a second y-axis needs to be added
|
|
389
|
+
if (displaySecondYAxis && metadata.length == 2) {
|
|
390
|
+
plotDataArr[1] = Object.assign(Object.assign({}, plotDataArr[1]), { yaxis: "y2" });
|
|
391
|
+
}
|
|
392
|
+
// Setting y-axis labels if needed and meeting the requirements
|
|
393
|
+
if (metadata.length == 1) {
|
|
394
|
+
setYAxisLabelLeft(yAxisLabel ? metadata[0].name : "");
|
|
395
|
+
setYAxisLabelLeftColor(yAxisLabel ? selectedTheme.colors.foreground : "");
|
|
396
|
+
}
|
|
397
|
+
else if (metadata.length == 2 && displaySecondYAxis) {
|
|
398
|
+
setYAxisLabelLeft(yAxisLabel ? metadata[0].name : "");
|
|
399
|
+
setYAxisLabelLeftColor(yAxisLabel ? metadata[0].color : "");
|
|
400
|
+
setYAxisLabelRight(yAxisLabel ? metadata[1].name : "");
|
|
401
|
+
setYAxisLabelRightColor(yAxisLabel ? metadata[1].color : "");
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
setYAxisLabelLeft("");
|
|
405
|
+
setYAxisLabelRight("");
|
|
406
|
+
setYAxisLabelLeftColor("");
|
|
407
|
+
setYAxisLabelRightColor("");
|
|
408
|
+
}
|
|
409
|
+
setPlotData(plotDataArr);
|
|
410
|
+
}, [
|
|
411
|
+
data,
|
|
412
|
+
metadata,
|
|
413
|
+
xScaleTickFormat,
|
|
414
|
+
xRange.length,
|
|
415
|
+
yAxisLabel,
|
|
416
|
+
displaySecondYAxis,
|
|
417
|
+
selectedTheme.colors.foreground,
|
|
418
|
+
selectedTheme.name,
|
|
419
|
+
]);
|
|
420
|
+
useEffect(() => {
|
|
421
|
+
updateLayout();
|
|
422
|
+
}, [updateLayout]);
|
|
423
|
+
useEffect(() => {
|
|
424
|
+
if (!scrubbing) {
|
|
425
|
+
setNowline(xRange.nowline);
|
|
426
|
+
}
|
|
427
|
+
sessionStorage.setItem("nl", xRange.nowline);
|
|
428
|
+
}, [scrubbing, xRange.nowline]);
|
|
429
|
+
const afterPlot = () => {
|
|
430
|
+
//console.log(plotlyRef.current);
|
|
431
|
+
//console.log(plotlyRef.current.el);
|
|
432
|
+
// TODO: get from plotlyRef instead of document
|
|
433
|
+
var layer = document.getElementsByClassName("axesclip")[0].firstChild;
|
|
434
|
+
const yAxisSignalLeft = layer.x.baseVal.value;
|
|
435
|
+
const yAxisSignalWidth = layer.width.baseVal.value;
|
|
436
|
+
const xAxisSignalTop = layer.y.baseVal.value;
|
|
437
|
+
const xAxisSignalHeight = layer.height.baseVal.value;
|
|
438
|
+
onRenderedLeft(yAxisSignalLeft);
|
|
439
|
+
onRenderedWidth(yAxisSignalWidth);
|
|
440
|
+
onRenderedTop(xAxisSignalTop);
|
|
441
|
+
onRenderedHeight(xAxisSignalHeight);
|
|
442
|
+
// TODO: get from plotlyRef instead of document
|
|
443
|
+
const scrubbar = document.getElementsByClassName("ewdrag")[0];
|
|
444
|
+
const scrubbarHeight = scrubbar.height.baseVal.value;
|
|
445
|
+
onRenderedScrubbar(scrubbarHeight);
|
|
446
|
+
};
|
|
447
|
+
const handleYValue = (yVal, idx) => {
|
|
448
|
+
// Noldus wants the Y data to be relative between 0 and 1
|
|
449
|
+
// MARIN data engineers always wants the data as it is
|
|
450
|
+
if (selectedTheme.name === "noldus" || shouldNormalize) {
|
|
451
|
+
const { min, max } = metadata[idx];
|
|
452
|
+
const range = max - min;
|
|
453
|
+
const y = yVal.map((value) => {
|
|
454
|
+
return (value - min) / range;
|
|
455
|
+
});
|
|
456
|
+
return y;
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
return yVal;
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
const getSignalData = (sharedSignalData, yVal) => {
|
|
463
|
+
if (selectedTheme.name === "noldus") {
|
|
464
|
+
const noldusSignalData = {
|
|
465
|
+
hovertemplate: "%{customdata:.2f}",
|
|
466
|
+
customdata: yVal.map((point) => `${point}`), // Setting raw data for each point
|
|
467
|
+
};
|
|
468
|
+
return Object.assign(Object.assign({}, sharedSignalData), noldusSignalData);
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
if (shouldNormalize) {
|
|
472
|
+
const marinSignalData = {
|
|
473
|
+
hovertemplate: "%{customdata}",
|
|
474
|
+
customdata: yVal.map((point) => `${point}`),
|
|
475
|
+
};
|
|
476
|
+
return Object.assign(Object.assign({}, sharedSignalData), marinSignalData);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
return sharedSignalData;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
return (React.createElement(StyledPlotly, { useResizeHandler: true, className: "plot-div", data: plotData, layout: layout, style: { width: "100%", height: percentageHeight + "%" }, config: {
|
|
484
|
+
displaylogo: false,
|
|
485
|
+
displayModeBar: false,
|
|
486
|
+
responsive: true,
|
|
487
|
+
doubleClick: false,
|
|
488
|
+
showTips: false,
|
|
489
|
+
}, onRelayout: (e) => onRelayout(e), onRelayouting: (e) => onRelayouting(e), onAfterPlot: () => afterPlot(), ref: plotlyRef }));
|
|
490
|
+
});
|
|
491
|
+
PlotlyPlayback.defaultProps = {
|
|
492
|
+
xRange: null,
|
|
493
|
+
data: [],
|
|
494
|
+
metadata: [],
|
|
495
|
+
onStopSelect: () => { },
|
|
496
|
+
onDrag: () => { },
|
|
497
|
+
xScaleTickFormat: "SS",
|
|
498
|
+
scrubbing: false,
|
|
499
|
+
yAxisLabel: false,
|
|
500
|
+
displaySecondYAxis: false,
|
|
501
|
+
displayArrow: true,
|
|
502
|
+
selectedTheme: null,
|
|
503
|
+
totalTime: null,
|
|
504
|
+
startPositionCurrentTimeIndicator: "0.5",
|
|
505
|
+
};
|
|
506
|
+
const dataElement = PropTypes.shape({
|
|
507
|
+
x: PropTypes.number,
|
|
508
|
+
y: PropTypes.number,
|
|
509
|
+
});
|
|
510
|
+
const metadataElement = PropTypes.shape({
|
|
511
|
+
name: PropTypes.string,
|
|
512
|
+
color: PropTypes.string,
|
|
513
|
+
});
|
|
514
|
+
PlotlyPlayback.propTypes = {
|
|
515
|
+
xRange: PropTypes.shape({
|
|
516
|
+
from: PropTypes.number,
|
|
517
|
+
length: PropTypes.number,
|
|
518
|
+
}),
|
|
519
|
+
data: PropTypes.arrayOf(PropTypes.arrayOf(dataElement), PropTypes.arrayOf(dataElement)),
|
|
520
|
+
metadata: PropTypes.arrayOf(metadataElement),
|
|
521
|
+
onStopSelect: PropTypes.func,
|
|
522
|
+
onDrag: PropTypes.func,
|
|
523
|
+
xScaleTickFormat: PropTypes.string,
|
|
524
|
+
scrubbing: PropTypes.bool,
|
|
525
|
+
yAxisLabel: PropTypes.bool,
|
|
526
|
+
displaySecondYAxis: PropTypes.bool,
|
|
527
|
+
displayArrow: PropTypes.bool,
|
|
528
|
+
selectedTheme: PropTypes.shape({
|
|
529
|
+
colors: PropTypes.shape({
|
|
530
|
+
background: PropTypes.string,
|
|
531
|
+
}),
|
|
532
|
+
name: PropTypes.string,
|
|
533
|
+
}),
|
|
534
|
+
totalTime: PropTypes.number,
|
|
535
|
+
startPositionCurrentTimeIndicator: PropTypes.string,
|
|
536
|
+
};
|
|
330
537
|
//# sourceMappingURL=PlotlyPlayback.js.map
|