Skip to content

Commit ec543f2

Browse files
committed
add series for trace
1 parent 7242835 commit ec543f2

File tree

3 files changed

+126
-43
lines changed

3 files changed

+126
-43
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,5 @@ env GITHUB_TOKEN=your_token yarn release-it patch
8383

8484
### Wishlist (help wanted)
8585

86-
- sizeref helper. I think this depends on the data. likely need to find the range and pick a good value?
87-
- load plotly.js from CDN?
86+
- sizeref helper. I think this depends on the data. likely need to find the range and pick a good value? From react?
8887
- nice to have: https://plot.ly/javascript/parallel-coordinates-plot/

src/anno.ts

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,73 @@
1-
import {Shape} from 'plotly.js';
2-
3-
export function processAnnotations(results: any): Shape[] {
4-
return results.annotations.map(a => {
5-
return {
6-
type: 'line', // rect
7-
xref: 'x',
8-
yref: 'paper',
9-
x0: a.time,
10-
y0: 0,
11-
x1: a.time,
12-
y1: 1,
13-
14-
visible: true,
15-
layer: 'above',
16-
17-
fillcolor: a.annotation.iconColor,
18-
opacity: 0.8,
19-
line: {
20-
color: a.annotation.iconColor,
21-
width: 2,
22-
dash: 'dash',
1+
import {Shape, Data} from 'plotly.js';
2+
3+
export class AnnoInfo {
4+
trace: Data;
5+
shapes: Shape[];
6+
7+
constructor() {
8+
this.clear();
9+
}
10+
11+
clear() {
12+
this.shapes = [];
13+
this.trace = {
14+
mode: 'markers',
15+
type: 'scatter',
16+
hoverinfo: 'x+text',
17+
x: [],
18+
y: [],
19+
text: [],
20+
yaxis: 'y2',
21+
marker: {
22+
size: 15,
23+
symbol: 'triangle-up',
24+
color: [],
2325
},
24-
} as Shape;
25-
});
26+
};
27+
}
28+
29+
update(results: any): boolean {
30+
if (!results || !results.annotations) {
31+
this.clear();
32+
return false;
33+
}
34+
35+
const x: number[] = [];
36+
const y: number[] = [];
37+
const text: string[] = [];
38+
const color: string[] = [];
39+
40+
this.shapes = results.annotations.map(a => {
41+
x.push(a.time);
42+
y.push(0);
43+
text.push('XXXX');
44+
color.push(a.annotation.iconColor);
45+
46+
return {
47+
type: 'line', // rect
48+
xref: 'x',
49+
yref: 'paper',
50+
x0: a.time,
51+
y0: 0,
52+
x1: a.time,
53+
y1: 1,
54+
55+
visible: true,
56+
layer: 'above',
57+
58+
fillcolor: a.annotation.iconColor,
59+
opacity: 0.8,
60+
line: {
61+
color: a.annotation.iconColor,
62+
width: 1,
63+
dash: 'dash',
64+
},
65+
} as Shape;
66+
});
67+
68+
// Overwrite it with new points
69+
this.trace = {...this.trace, x, y, text};
70+
this.trace.marker!.color = color;
71+
return x.length > 0;
72+
}
2673
}

src/module.ts

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import {
1717
import {EditorHelper} from './editor';
1818

1919
import {loadPlotly, loadIfNecessary} from './libLoader';
20-
import {processAnnotations} from './anno';
21-
import {Shape} from 'plotly.js';
20+
import {AnnoInfo} from './anno';
21+
import {Axis} from 'plotly.js';
2222

2323
let Plotly: any; // Loaded dynamically!
2424

@@ -66,6 +66,14 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
6666
color_option: 'ramp',
6767
},
6868
};
69+
70+
static yaxis2: Partial<Axis> = {
71+
title: 'Annotations',
72+
type: 'linear',
73+
range: [0, 1],
74+
visible: false,
75+
};
76+
6977
static defaults = {
7078
pconfig: {
7179
loadFromCDN: false,
@@ -107,7 +115,7 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
107115
};
108116

109117
graphDiv: any;
110-
annotations: Shape[];
118+
annotations = new AnnoInfo();
111119
series: SeriesWrapper[];
112120
seriesByKey: Map<string, SeriesWrapper> = new Map();
113121
seriesHash = '?';
@@ -208,7 +216,7 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
208216

209217
onDataError(err) {
210218
this.series = [];
211-
this.annotations = [];
219+
this.annotations.clear();
212220
this.render();
213221
}
214222

@@ -363,6 +371,9 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
363371
layout.xaxis.gridcolor = color;
364372
layout.yaxis.gridcolor = color;
365373
}
374+
375+
// Set the second axis
376+
layout.yaxis2 = PlotlyPanelCtrl.yaxis2;
366377
}
367378
return layout;
368379
}
@@ -388,8 +399,12 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
388399
};
389400

390401
this.layout = this.getProcessedLayout();
391-
this.layout.shapes = this.annotations;
392-
Plotly.react(this.graphDiv, this.traces, this.layout, options);
402+
this.layout.shapes = this.annotations.shapes;
403+
let traces = this.traces;
404+
if (this.annotations.shapes.length > 0) {
405+
traces = this.traces.concat(this.annotations.trace);
406+
}
407+
Plotly.react(this.graphDiv, traces, this.layout, options);
393408

394409
this.graphDiv.on('plotly_click', data => {
395410
if (data === undefined || data.points === undefined) {
@@ -442,8 +457,9 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
442457
let max = Number.MIN_SAFE_INTEGER;
443458

444459
for (let i = 0; i < data.points.length; i++) {
445-
const idx = data.points[i].pointNumber;
446-
const ts = this.traces[0].ts[idx];
460+
const found = data.points[i];
461+
const idx = found.pointNumber;
462+
const ts = found.fullData.x[idx];
447463
min = Math.min(min, ts);
448464
max = Math.max(max, ts);
449465
}
@@ -477,6 +493,8 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
477493
this.onDataReceived(snapshot);
478494
}
479495

496+
_hadAnno = false;
497+
480498
onDataReceived(dataList) {
481499
const finfo: SeriesWrapper[] = [];
482500
let seriesHash = '/';
@@ -527,25 +545,39 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
527545
}
528546

529547
// Support Annotations
548+
let annotationPromise = Promise.resolve();
530549
if (this.is3d()) {
531-
this.annotations = [];
532-
this.layout.shapes = this.annotations;
550+
this.annotations.clear();
551+
if (this.layout) {
552+
if (this.layout.shapes) {
553+
this.onConfigChanged();
554+
}
555+
this.layout.shapes = [];
556+
}
533557
} else {
534-
this.annotationsSrv
558+
annotationPromise = this.annotationsSrv
535559
.getAnnotations({
536560
dashboard: this.dashboard,
537561
panel: this.panel,
538562
range: this.range,
539563
})
540564
.then(results => {
541-
this.annotations = processAnnotations(results);
542-
this.layout.shapes = this.annotations;
565+
const hasAnno = this.annotations.update(results);
566+
if (this.layout) {
567+
if (hasAnno !== this._hadAnno) {
568+
this.onConfigChanged();
569+
}
570+
this.layout.shapes = this.annotations.shapes;
571+
}
572+
this._hadAnno = hasAnno;
543573
});
544574
}
545575

546576
// Load the real data changes
547-
this._updateTraceData();
548-
this.render();
577+
annotationPromise.then(() => {
578+
this._updateTraceData();
579+
this.render();
580+
});
549581
}
550582

551583
__addCopyPath(trace: any, key: string, path: string) {
@@ -699,8 +731,13 @@ class PlotlyPanelCtrl extends MetricsPanelCtrl {
699731
modeBarButtonsToRemove: ['sendDataToCloud'], //, 'select2d', 'lasso2d']
700732
};
701733
this.layout = this.getProcessedLayout();
702-
this.layout.shapes = this.annotations;
703-
Plotly.react(this.graphDiv, this.traces, this.layout, options);
734+
this.layout.shapes = this.annotations.shapes;
735+
let traces = this.traces;
736+
if (this.annotations.shapes.length > 0) {
737+
traces = this.traces.concat(this.annotations.trace);
738+
}
739+
console.log('ConfigChanged (traces)', traces);
740+
Plotly.react(this.graphDiv, traces, this.layout, options);
704741
}
705742

706743
this.render(); // does not query again!

0 commit comments

Comments
 (0)