UNPKG

@senx/warpview

Version:
558 lines 108 kB
/* * Copyright 2021 SenX S.A.S. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { Component, ElementRef, EventEmitter, HostListener, Input, NgZone, Output, Renderer2, ViewEncapsulation } from '@angular/core'; import { WarpViewComponent } from '../warp-view-component'; import { ChartLib } from '../../utils/chart-lib'; import moment from 'moment-timezone'; import { GTSLib } from '../../utils/gts.lib'; import { ColorLib } from '../../utils/color-lib'; import { SizeService } from '../../services/resize.service'; import { Logger } from '../../utils/logger'; import { ChartBounds } from '../../model/chartBounds'; import * as i0 from "@angular/core"; import * as i1 from "../../services/resize.service"; import * as i2 from "../warp-view-spinner/warp-view-spinner.component"; import * as i3 from "../../plotly/plotly.component"; import * as i4 from "@angular/common"; export class WarpViewAnnotationComponent extends WarpViewComponent { constructor(el, renderer, sizeService, ngZone) { super(el, renderer, sizeService, ngZone); this.el = el; this.renderer = renderer; this.sizeService = sizeService; this.ngZone = ngZone; this.height = 0; this.pointHover = new EventEmitter(); this.chartDraw = new EventEmitter(); this.boundsDidChange = new EventEmitter(); this.displayExpander = true; this.layout = { showlegend: false, hovermode: 'closest', xaxis: { gridwidth: 1, fixedrange: false, autorange: false, automargin: false, showticklabels: true, showgrid: false }, autosize: false, autoexpand: false, yaxis: { showticklabels: false, fixedrange: true, dtick: 1, gridwidth: 1, tick0: 0, nticks: 1, rangemode: 'tozero', tickson: 'boundaries', automargin: false, autorange: false, showline: false, zeroline: true }, margin: { t: 2, b: 50, r: 10, l: 10 }, }; this.marginLeft = 50; this.expanded = false; // tslint:disable-next-line:variable-name this._type = 'annotation'; this.visibility = []; this._standalone = true; this.maxTick = Number.MIN_VALUE; this.minTick = Number.MAX_VALUE; this.visibleGtsId = []; this.gtsId = []; this.dataHashset = {}; this.lineHeight = 30; this.chartBounds = new ChartBounds(); this.afterBoundsUpdate = false; this.firstDraw = true; this._autoResize = false; this.LOG = new Logger(WarpViewAnnotationComponent, this._debug); } set type(type) { this.LOG.debug(['type'], type); this._type = type; this.drawChart(); } set hiddenData(hiddenData) { const previousVisibility = JSON.stringify(this.visibility); this.LOG.debug(['hiddenData', 'previousVisibility'], previousVisibility); this._hiddenData = hiddenData; this.visibility = []; this.visibleGtsId.forEach(id => this.visibility.push(hiddenData.indexOf(id) < 0 && (id !== -1))); this.LOG.debug(['hiddenData', 'hiddendygraphfullv'], this.visibility); const newVisibility = JSON.stringify(this.visibility); this.LOG.debug(['hiddenData', 'json'], previousVisibility, newVisibility); if (previousVisibility !== newVisibility) { const visible = []; const hidden = []; this.gtsId.forEach((id, i) => { if (this._hiddenData.indexOf(id) > -1) { hidden.push(i); } else { visible.push(i); } }); if (visible.length > 0) { this.graph.restyleChart({ visible: true }, visible); } if (hidden.length > 0) { this.graph.restyleChart({ visible: false }, hidden); } this.LOG.debug(['hiddendygraphtrig', 'destroy'], 'redraw by visibility change'); } } set standalone(isStandalone) { this.LOG.debug(['standalone'], isStandalone); if (this._standalone !== isStandalone) { this._standalone = isStandalone; this.drawChart(); } } get standalone() { return this._standalone; } handleKeyDown($event) { if ($event.key === 'Control') { this.trimmed = setInterval(() => { if (!!this.toolTip.nativeElement.querySelector('#tooltip-body')) { this.toolTip.nativeElement.querySelector('#tooltip-body').classList.add('full'); } }, 100); } } handleKeyup($event) { this.LOG.debug(['document:keyup'], $event); if ($event.key === 'Control') { if (!!this.toolTip.nativeElement.querySelector('#tooltip-body')) { if (this.trimmed) { clearInterval(this.trimmed); } this.toolTip.nativeElement.querySelector('#tooltip-body').classList.remove('full'); } } } update(options, refresh) { this.drawChart(refresh); } updateBounds(min, max, marginLeft) { this.LOG.debug(['updateBounds'], min, max, this._options); this._options.bounds = this._options.bounds || {}; this._options.bounds.minDate = min; this._options.bounds.maxDate = max; this.layout.xaxis.autorange = false; this.LOG.debug(['updateBounds'], GTSLib.toISOString(min, this.divider, this._options.timeZone), GTSLib.toISOString(max, this.divider, this._options.timeZone)); this.minTick = min; this.maxTick = max; if (this._options.timeMode && this._options.timeMode === 'timestamp') { this.layout.xaxis.tick0 = min; this.layout.xaxis.range = [min, max]; } else { this.layout.xaxis.tick0 = GTSLib.toISOString(min, this.divider, this._options.timeZone); this.layout.xaxis.range = [ GTSLib.toISOString(min, this.divider, this._options.timeZone), GTSLib.toISOString(max, this.divider, this._options.timeZone) ]; } this.layout.margin.l = marginLeft; this.marginLeft = marginLeft; this.layout = { ...this.layout }; this.LOG.debug(['updateBounds'], { ...this.layout.xaxis.range }); this.afterBoundsUpdate = true; } drawChart(reparseNewData = false) { this.loading = true; this.layout.margin.l = !!this._standalone ? 10 : 50; this.layout.margin.b = !!this._standalone ? 50 : 2; this.height = this.lineHeight * (this.expanded ? this.gtsId.length : 1) + this.layout.margin.t + this.layout.margin.b; this.LOG.debug(['drawChart', 'this.height'], this.height, this.expanded); if (this.firstDraw && reparseNewData) { this.expanded = !!this._options.expandAnnotation; } this.layout.height = this.height; if (!this.initChart(this.el)) { return; } this.el.nativeElement.style.display = 'block'; this.LOG.debug(['drawChart', 'this.plotlyData'], this.plotlyData); this.LOG.debug(['drawChart', 'hiddenData'], this._hiddenData); this.LOG.debug(['drawChart', 'this._options.bounds'], this._options.bounds, this._options.timeMode); this.layout.yaxis.color = this.getGridColor(this.el.nativeElement); this.layout.yaxis.gridcolor = this.getGridColor(this.el.nativeElement); this.layout.yaxis.showline = !!this._standalone; this.layout.yaxis.zerolinecolor = this.getGridColor(this.el.nativeElement); this.layout.xaxis.color = this.getGridColor(this.el.nativeElement); this.layout.xaxis.gridcolor = this.getGridColor(this.el.nativeElement); this.layout.xaxis.autorange = !!this._standalone; this.layout.xaxis.showticklabels = !!this._standalone; this.displayExpander = (this.plotlyData.length > 1); const count = this.plotlyData.filter(d => d.y.length > 0).length; const calculatedHeight = this.lineHeight * (this.expanded ? count : 1) + this.layout.margin.t + this.layout.margin.b; this.el.nativeElement.style.height = (calculatedHeight + 30) + 'px'; this.height = calculatedHeight; this.layout.height = this.height; this.LOG.debug(['drawChart', 'height'], this.lineHeight, this.height, count, calculatedHeight, this.expanded, this.layout.margin); this.layout.yaxis.range = [0, this.expanded ? count : 1]; this.LOG.debug(['drawChart', 'this.layout'], this.layout, this.expanded); if (this._options.timeMode && this._options.timeMode === 'timestamp') { this.layout.xaxis.tick0 = this.minTick; this.layout.xaxis.range = [this.minTick, this.maxTick]; this.layout.xaxis.type = 'linear'; } else { this.layout.xaxis.tick0 = GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone); this.layout.xaxis.range = [ GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone), GTSLib.toISOString(this.maxTick, this.divider, this._options.timeZone) ]; this.layout.xaxis.type = 'date'; } this.plotlyConfig.scrollZoom = true; this.layout.xaxis.showgrid = false; setTimeout(() => { this.plotlyConfig = { ...this.plotlyConfig }; this.layout = { ...this.layout }; this.firstDraw = false; }); this.LOG.debug(['drawChart', 'this.plotlyConfig'], this.plotlyConfig, this.plotlyData, this.layout); } relayout(data) { let change = false; this.LOG.debug(['relayout', 'updateBounds'], data); if (data['xaxis.range'] && data['xaxis.range'].length === 2) { if (this.chartBounds.msmin !== data['xaxis.range'][0] || this.chartBounds.msmax !== data['xaxis.range'][1]) { this.LOG.debug(['relayout', 'updateBounds', 'xaxis.range'], data['xaxis.range']); change = true; this.chartBounds.msmin = data['xaxis.range'][0]; this.chartBounds.msmax = data['xaxis.range'][1]; this.chartBounds.tsmin = GTSLib.toTimestamp(this.chartBounds.msmin, this.divider, this._options.timeZone); this.chartBounds.tsmax = GTSLib.toTimestamp(this.chartBounds.msmax, this.divider, this._options.timeZone); } } else if (data['xaxis.range[0]'] && data['xaxis.range[1]']) { if (this.chartBounds.msmin !== data['xaxis.range[0]'] || this.chartBounds.msmax !== data['xaxis.range[1]']) { this.LOG.debug(['relayout', 'updateBounds', 'xaxis.range[x]'], data['xaxis.range[0]'], data['xaxis.range[1]']); change = true; this.chartBounds.msmin = data['xaxis.range[0]']; this.chartBounds.msmax = data['xaxis.range[1]']; this.chartBounds.tsmin = GTSLib.toTimestamp(this.chartBounds.msmin, this.divider, this._options.timeZone); this.chartBounds.tsmax = GTSLib.toTimestamp(this.chartBounds.msmax, this.divider, this._options.timeZone); } } else if (data['xaxis.autorange']) { if (this.chartBounds.tsmin !== this.minTick || this.chartBounds.tsmax !== this.maxTick) { this.LOG.debug(['relayout', 'updateBounds', 'autorange'], data, this.minTick, this.maxTick); change = true; this.chartBounds.tsmin = this.minTick; this.chartBounds.tsmax = this.maxTick; } } if (change) { this.LOG.debug(['relayout', 'updateBounds'], this.minTick, this.maxTick); this.LOG.debug(['relayout', 'updateBounds'], this.chartBounds); if (this._options.timeMode && this._options.timeMode === 'timestamp') { this.emitNewBounds(this.chartBounds.msmin, this.chartBounds.msmax); } else { this.emitNewBounds(this.chartBounds.tsmin, this.chartBounds.tsmax); } } this.loading = false; this.afterBoundsUpdate = false; this.chartDraw.emit(); } hover(data) { this.LOG.debug(['hover'], data); const tooltip = this.toolTip.nativeElement; const color = data.points[0].fullData.marker.color; this.pointHover.emit({ x: data.event.offsetX, y: data.event.offsetY }); let x = data.xvals[0]; if (!!data.points[0]) { x = data.points[0].x; } const layout = this.el.nativeElement.getBoundingClientRect(); const count = this.plotlyData.filter(d => d.y.length > 0).length; tooltip.style.opacity = '1'; tooltip.style.display = 'block'; tooltip.style.paddingLeft = (this._standalone ? 0 : 40) + 'px'; tooltip.style.top = (((this.expanded ? count - data.points[0].y : 0.5) * this.lineHeight) + this.layout.margin.t) + 'px'; tooltip.classList.remove('right', 'left'); tooltip.innerHTML = `<div class="tooltip-body trimmed" id="tooltip-body"> <span class="tooltip-date">${this._options.timeMode === 'timestamp' ? x : (moment.utc(x).toISOString().replace('Z', this._options.timeZone === 'UTC' ? 'Z' : '') || '')}</span> <i class="chip" style="background-color: ${color};border: 2px solid ${color};"></i>&nbsp;${GTSLib.formatLabel(data.points[0].data.name)}: <span class="value">${data.points[0].text}</span> </div>`; if (data.event.offsetX > layout.width / 2) { tooltip.classList.add('left'); } else { tooltip.classList.add('right'); } tooltip.style.pointerEvents = 'none'; } unhover() { this.toolTip.nativeElement.style.display = 'none'; } afterPlot(div) { this.loading = false; this.chartBounds.tsmin = this.minTick; this.chartBounds.tsmax = this.maxTick; this.LOG.debug(['afterPlot'], 'div', div); this.chartDraw.emit(this.chartBounds); if (this.afterBoundsUpdate || this._standalone) { this.chartDraw.emit(this.chartBounds); this.LOG.debug(['afterPlot'], 'chartBounds', this.chartBounds, div); this.afterBoundsUpdate = false; } } emitNewBounds(min, max) { this.LOG.debug(['emitNewBounds'], min, max); if (this._options.timeMode && this._options.timeMode === 'timestamp') { this.boundsDidChange.emit({ bounds: { min, max }, source: 'annotation' }); } else { this.boundsDidChange.emit({ bounds: { min: moment.tz(min, this._options.timeZone).valueOf(), max: moment.tz(max, this._options.timeZone).valueOf() }, source: 'annotation' }); } } convert(data, firstDraw = false) { this.loading = true; this.noData = true; const dataset = []; let gtsList = GTSLib.flatDeep(GTSLib.flattenGtsIdArray(data.data, 0).res); this.maxTick = Number.NEGATIVE_INFINITY; this.minTick = Number.POSITIVE_INFINITY; this.visibleGtsId = []; this.gtsId = []; const nonPlottable = gtsList.filter(g => g.v && GTSLib.isGtsToPlot(g)); gtsList = gtsList.filter(g => g.v && !GTSLib.isGtsToPlot(g)); let timestampMode = firstDraw; if (firstDraw) { const tsLimit = 100 * GTSLib.getDivider(this._options.timeUnit); gtsList.forEach((gts) => { const ticks = gts.v.map(t => t[0]); const size = gts.v.length; timestampMode = timestampMode && (ticks[0] > -tsLimit && ticks[0] < tsLimit); timestampMode = timestampMode && (ticks[size - 1] > -tsLimit && ticks[size - 1] < tsLimit); }); } if (timestampMode || this._options.timeMode === 'timestamp') { this.layout.xaxis.type = 'linear'; } else { this.layout.xaxis.type = 'date'; } gtsList.forEach((gts, i) => { if (gts.v) { const size = gts.v.length; const label = GTSLib.serializeGtsMetadata(gts); const c = ColorLib.getColor(gts.id, this._options.scheme); const color = ((data.params || [])[i] || { datasetColor: c }).datasetColor || c; const series = { type: 'scattergl', mode: 'markers', name: label, x: [], y: [], text: [], hoverinfo: 'none', connectgaps: false, visible: !(this._hiddenData.filter(h => h === gts.id).length > 0), line: { color }, marker: { symbol: 'line-ns-open', color, size: 20, width: 5, } }; this.visibleGtsId.push(gts.id); this.gtsId.push(gts.id); if (timestampMode || !!this._options.timeMode && this._options.timeMode === 'timestamp') { this.layout.xaxis.type = 'linear'; } else { this.layout.xaxis.type = 'date'; } const ticks = []; series.text = []; series.y = []; if (size > 0) { for (let v = 0; v < size; v++) { const val = gts.v[v]; const t = val[0]; ticks.push(t); series.text.push(val[val.length - 1]); series.y.push((this.expanded ? i : 0) + 0.5); this.minTick = (t < this.minTick) ? t : this.minTick; this.maxTick = (t > this.maxTick) ? t : this.maxTick; } } if (timestampMode || this._options.timeMode === 'timestamp') { series.x = ticks; } else { series.x = ticks.map(t => GTSLib.toISOString(t, this.divider, this._options.timeZone)); } if (series.x.length > 0) { dataset.push(series); } } }); this.LOG.debug(['convert'], 'forEach value end', this.minTick, this.maxTick); if (nonPlottable.length > 0) { nonPlottable.forEach(g => { g.v.forEach(value => { const ts = value[0]; if (ts < this.minTick) { this.minTick = ts; } if (ts > this.maxTick) { this.maxTick = ts; } }); }); // if there is not any plottable data, we must add a fake one with id -1. This one will always be hidden. if (0 === gtsList.length) { if (!this.dataHashset[this.minTick]) { this.dataHashset[this.minTick] = [0]; } if (!this.dataHashset[this.maxTick]) { this.dataHashset[this.maxTick] = [0]; } this.visibility.push(false); this.visibleGtsId.push(-1); } } const x = { ...this.layout.xaxis, tick0: undefined, range: [] }; const pad = ChartLib.fraction2r(this.minTick, this.maxTick, 0.067); if (timestampMode || !!this._options.timeMode && this._options.timeMode === 'timestamp') { x.tick0 = this.minTick - pad; x.range = [x.tick0, this.maxTick + pad]; } else { x.tick0 = GTSLib.toISOString(this.minTick - pad, this.divider, this._options.timeZone); x.range = [x.tick0, GTSLib.toISOString(this.maxTick + pad, this.divider, this._options.timeZone)]; } this.layout.xaxis = x; this.noData = dataset.length === 0; const count = dataset.filter(d => d.y.length > 0).length; this.layout.yaxis.range = [0, this.expanded ? count : 1]; this.LOG.debug(['convert end'], dataset, timestampMode || !!this._options.timeMode && this._options.timeMode === 'timestamp'); return dataset; } toggle() { this.LOG.debug(['this.expanded'], !!this.expanded); this.expanded = !this.expanded; this.drawChart(false); } setRealBounds(chartBounds) { this.LOG.debug(['setRealBounds'], chartBounds, this._options.timeMode); this.afterBoundsUpdate = true; this.minTick = chartBounds.tsmin; this.maxTick = chartBounds.tsmax; this._options.bounds = this._options.bounds || {}; this._options.bounds.minDate = this.minTick; this._options.bounds.maxDate = this.maxTick; const x = { tick0: undefined, range: [], }; if (this._options.showRangeSelector) { x.rangeslider = { bgcolor: 'transparent', thickness: 40 / this.height }; } if (!!this._options.timeMode && this._options.timeMode === 'timestamp') { x.tick0 = this.minTick / this.divider; x.range = [this.minTick, this.maxTick]; } else { x.tick0 = GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone); x.range = [ GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone), GTSLib.toISOString(this.maxTick, this.divider, this._options.timeZone) ]; } this.layout.xaxis = x; this.layout = { ...this.layout }; } resize(layout) { // } } WarpViewAnnotationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: WarpViewAnnotationComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.SizeService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); WarpViewAnnotationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.1", type: WarpViewAnnotationComponent, selector: "warpview-annotation", inputs: { type: "type", hiddenData: "hiddenData", standalone: "standalone", height: "height" }, outputs: { pointHover: "pointHover", chartDraw: "chartDraw", boundsDidChange: "boundsDidChange" }, host: { listeners: { "keydown": "handleKeyDown($event)", "document:keydown": "handleKeyDown($event)", "keyup": "handleKeyup($event)", "document:keyup": "handleKeyup($event)" } }, usesInheritance: true, ngImport: i0, template: "<!--\n ~ Copyright 2021 SenX S.A.S.\n ~\n ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ http://www.apache.org/licenses/LICENSE-2.0\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n ~\n -->\n<div id=\"chartContainer\" #chartContainer (mouseleave)=\"hideTooltip()\">\n <button *ngIf=\"displayExpander && plotlyData && plotlyData.length > 1\" class=\"expander\" (click)=\"toggle()\"\n title=\"collapse/expand\">+/-\n </button>\n <div #toolTip class=\"wv-tooltip\"></div>\n <warpview-spinner *ngIf=\"loading\" message=\"Parsing data\"></warpview-spinner>\n <div *ngIf=\"!loading && !noData\" class=\"annotation-wrapper\">\n <div class=\"upperLine\" [ngStyle]=\"{left: standalone? '10px': marginLeft + 'px'}\"></div>\n <warpview-plotly #graph\n [data]=\"plotlyData\" [layout]=\"layout\" [config]=\"plotlyConfig\" (afterPlot)=\"afterPlot($event)\"\n (relayout)=\"relayout($event)\" className=\"chart\" (hover)=\"hover($event)\" (unhover)=\"unhover()\"\n [updateOnLayoutChange]=\"true\" [updateOnDataChange]=\"true\" [debug]=\"debug\"\n [style]=\"{position: 'relative', width: '100%', height: '100%'}\"></warpview-plotly>\n </div>\n</div>\n", styles: [":root{--warp-view-chart-width: 100%;--warp-view-chart-height: 100%;--warp-view-datagrid-cell-padding: 5px;--warp-view-map-margin: 0;--warp-view-switch-height: 30px;--warp-view-switch-width: 100px;--warp-view-switch-radius: 18px;--warp-view-plot-chart-height: 100%;--warp-view-slider-pointer-size: 65px;--warp-view-resize-handle-height: 10px;--warp-view-tile-width: 100%;--warp-view-tile-height: 100%;--warp-view-font-color: #000000;--warp-view-bar-color: #dc3545;--warp-view-datagrid-odd-bg-color: #ffffff;--warp-view-datagrid-odd-color: #404040;--warp-view-datagrid-even-bg-color: #c0c0c0;--warp-view-datagrid-even-color: #000000;--warp-view-pagination-border-color: #c0c0c0;--warp-view-pagination-bg-color: #ffffff;--warp-view-pagination-active-bg-color: #4CAF50;--warp-view-pagination-active-color: #ffffff;--warp-view-pagination-active-border-color: #4CAF50;--warp-view-pagination-hover-bg-color: #c0c0c0;--warp-view-pagination-hover-color: #000000;--warp-view-pagination-hover-border-color: #c0c0c0;--warp-view-pagination-disabled-color: #c0c0c0;--warp-view-switch-inset-color: #c0c0c0;--warp-view-switch-inset-checked-color: #00cd00;--warp-view-switch-handle-color: radial-gradient(#ffffff 15%, #c0c0c0 100%);--warp-view-switch-handle-checked-color: radial-gradient(#ffffff 15%, #00cd00 100%);--warp-view-resize-handle-color: #c0c0c0;--warp-view-chart-legend-bg: #ffffff;--warp-view-chart-legend-color: #404040;--gts-classname-font-color: #004eff;--gts-labelname-font-color: #19A979;--gts-attrname-font-color: #ED4A7B;--gts-separator-font-color: #a0a0a0;--gts-labelvalue-font-color: #000000;--gts-attrvalue-font-color: #000000;--gts-stack-font-color: #000000;--gts-tree-expanded-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA7klEQVQ4T82TMW7CQBBF/0g+QOpINEkVCmpaLoBm5COk5QYoaeAY3MDSei2LGu4QKakiBA1tCpTK8kS2sLVe2xSh8XSrnf9m/s4s4c6gO/UYGEBEXlT1bK396bFGIjIJguA7iqJLkVNbYOZXItoQ0QHAzBhz9CCFeAVgCeAjy7Jpmqa/NUBEEgDzktqGuOKKO47j+KsGhGH4lOf5HsDIg5ycyqVYVd+steuGheLAzM9EtPMgW1VdVGWJ6N0YU1gpozVGH+K+gy/uBHR1crXUqNzbQXXhduJ69sd7cxOZ+UFVH5Mk+exb+YGt8n9+5h8up1sReYC0WAAAAABJRU5ErkJggg==);--gts-tree-collapsed-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA0UlEQVQ4T6WTUW7CQAxEPQdozxYb9Qb94Aj9gQSoVCp6lMr21doDZFCQiFCU3YDY//d2PeOFPHnwJC+zAlVdA/jp+/6YmZ+1S0qCPxF5HUAAO3fvSpKS4ENEvm6gfUS0c5JiBma2Ibm/QiQPmbmdSqohquoA7GqSxRaapmkBjBkAeHP336t0UWBmHcnb+VcR4XcJpjDJLjPHkS4tleqZubmNiDHU6gumDQDYuvvh7hpV9V9EXgaA5Ka2jbMjmNk7yZOIfEfE8eFVfuSDLda4JDsD3FNdEckTC0YAAAAASUVORK5CYII=);--warp-view-popup-bg-color: #ffffff;--warp-view-popup-border-color: rgba(0, 0, 0, .2);--warp-view-popup-header-bg-color: #c0c0c0;--warp-view-popup-title-color: #404040;--warp-view-popup-close-color: #404040;--warp-view-popup-body-bg-color: #ffffff;--warp-view-popup-body-color: #000000;--warp-view-annotationtooltip-value-font-color: #004eff;--warp-view-annotationtooltip-font-color: #404040;--warp-view-spinner-color: #ff9900;--warp-view-tooltip-bg: #ffffff;--warp-view-tooltip-color: #000000;--warp-slider-connect-color: #ff9900;--warp-slider-handle-bg-color: #ffffff;--warp-slider-handle-color: #004eff;--warp-slider-handle-shadow: inset 0 0 1px #ffffff, inset 0 1px 7px #c0c0c0, 0 3px 6px -3px #a0a0a0}.noData{width:100%;text-align:center;color:var(--warp-view-chart-legend-color);position:relative}.js-plotly-plot .plotly .cursor-ew-resize{cursor:default!important}/*!\n * Copyright 2021 SenX S.A.S.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */.gts-classname{color:var(--gts-classname-font-color)}.gts-labelname{color:var(--gts-labelname-font-color)}.gts-attrname{color:var(--gts-attrname-font-color)}.gts-separator{color:var(--gts-separator-font-color)}.gts-labelvalue{color:var(--gts-labelvalue-font-color);font-style:italic}.gts-attrvalue{color:var(--gts-attrvalue-font-color);font-style:italic}:host{display:block}:host .expander{position:absolute;top:0;left:0;width:35px;z-index:9}:host #chartContainer{height:auto;position:relative;padding-top:30px}:host #chartContainer div.upperLine{position:absolute;top:0;left:0;height:0;border-bottom:1px solid var(--warp-view-chart-grid-color, #8e8e8e);right:10px}:host #chartContainer .annotation-wrapper{position:relative}:host .date{text-align:right;display:block;height:20px;vertical-align:middle;line-height:20px;position:absolute;top:0;left:40px}:host .chart{width:var(--warp-view-chart-width);height:var(--warp-view-chart-height)}:host .wv-tooltip{position:absolute;width:calc(100% - 50px);z-index:999;margin-left:10px;top:-1000px;font-size:10px}:host .wv-tooltip .tooltip-body{border:1px solid grey;border-radius:5px;background-color:var(--warp-view-tooltip-bg)!important;color:var(--warp-view-tooltip-color)!important;padding-left:10px;padding-right:10px;width:auto;max-width:100%;vertical-align:middle;line-height:10px;height:40px;overflow:visible;margin:1px}:host .wv-tooltip .tooltip-body .chip{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;cursor:pointer}:host .wv-tooltip .tooltip-body.trimmed{max-width:49%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body.full{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body .value{color:var(--warp-view-annotationtooltip-value-font-color)}:host .wv-tooltip .tooltip-body .tooltip-date{font-weight:700;text-align:left;display:block;width:100%;height:.8rem;padding-top:5px;padding-bottom:5px;vertical-align:middle;line-height:.8rem}:host .wv-tooltip .tooltip-body .round{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;margin-right:5px}:host .wv-tooltip.left .tooltip-body{text-align:left;float:left}:host .wv-tooltip.left .tooltip-body .tooltip-date{text-align:left}:host .wv-tooltip.right .tooltip-body{float:right}\n"], components: [{ type: i2.WarpViewSpinnerComponent, selector: "warpview-spinner", inputs: ["message"] }, { type: i3.PlotlyComponent, selector: "warpview-plotly", inputs: ["data", "layout", "config", "debug", "frames", "style", "divId", "revision", "className", "useResizeHandler", "updateOnLayoutChange", "updateOnDataChange", "updateOnlyWithRevision"], outputs: ["initialized", "update", "purge", "error", "afterExport", "afterPlot", "animated", "animatingFrame", "animationInterrupted", "autoSize", "beforeExport", "buttonClicked", "click", "plotly_click", "clickAnnotation", "deselect", "doubleClick", "framework", "hover", "legendClick", "legendDoubleClick", "relayout", "restyle", "redraw", "selected", "selecting", "sliderChange", "sliderEnd", "sliderStart", "transitioning", "transitionInterrupted", "unhover", "relayouting"] }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], encapsulation: i0.ViewEncapsulation.ShadowDom }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: WarpViewAnnotationComponent, decorators: [{ type: Component, args: [{ selector: 'warpview-annotation', encapsulation: ViewEncapsulation.ShadowDom, template: "<!--\n ~ Copyright 2021 SenX S.A.S.\n ~\n ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ http://www.apache.org/licenses/LICENSE-2.0\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n ~\n -->\n<div id=\"chartContainer\" #chartContainer (mouseleave)=\"hideTooltip()\">\n <button *ngIf=\"displayExpander && plotlyData && plotlyData.length > 1\" class=\"expander\" (click)=\"toggle()\"\n title=\"collapse/expand\">+/-\n </button>\n <div #toolTip class=\"wv-tooltip\"></div>\n <warpview-spinner *ngIf=\"loading\" message=\"Parsing data\"></warpview-spinner>\n <div *ngIf=\"!loading && !noData\" class=\"annotation-wrapper\">\n <div class=\"upperLine\" [ngStyle]=\"{left: standalone? '10px': marginLeft + 'px'}\"></div>\n <warpview-plotly #graph\n [data]=\"plotlyData\" [layout]=\"layout\" [config]=\"plotlyConfig\" (afterPlot)=\"afterPlot($event)\"\n (relayout)=\"relayout($event)\" className=\"chart\" (hover)=\"hover($event)\" (unhover)=\"unhover()\"\n [updateOnLayoutChange]=\"true\" [updateOnDataChange]=\"true\" [debug]=\"debug\"\n [style]=\"{position: 'relative', width: '100%', height: '100%'}\"></warpview-plotly>\n </div>\n</div>\n", styles: [":root{--warp-view-chart-width: 100%;--warp-view-chart-height: 100%;--warp-view-datagrid-cell-padding: 5px;--warp-view-map-margin: 0;--warp-view-switch-height: 30px;--warp-view-switch-width: 100px;--warp-view-switch-radius: 18px;--warp-view-plot-chart-height: 100%;--warp-view-slider-pointer-size: 65px;--warp-view-resize-handle-height: 10px;--warp-view-tile-width: 100%;--warp-view-tile-height: 100%;--warp-view-font-color: #000000;--warp-view-bar-color: #dc3545;--warp-view-datagrid-odd-bg-color: #ffffff;--warp-view-datagrid-odd-color: #404040;--warp-view-datagrid-even-bg-color: #c0c0c0;--warp-view-datagrid-even-color: #000000;--warp-view-pagination-border-color: #c0c0c0;--warp-view-pagination-bg-color: #ffffff;--warp-view-pagination-active-bg-color: #4CAF50;--warp-view-pagination-active-color: #ffffff;--warp-view-pagination-active-border-color: #4CAF50;--warp-view-pagination-hover-bg-color: #c0c0c0;--warp-view-pagination-hover-color: #000000;--warp-view-pagination-hover-border-color: #c0c0c0;--warp-view-pagination-disabled-color: #c0c0c0;--warp-view-switch-inset-color: #c0c0c0;--warp-view-switch-inset-checked-color: #00cd00;--warp-view-switch-handle-color: radial-gradient(#ffffff 15%, #c0c0c0 100%);--warp-view-switch-handle-checked-color: radial-gradient(#ffffff 15%, #00cd00 100%);--warp-view-resize-handle-color: #c0c0c0;--warp-view-chart-legend-bg: #ffffff;--warp-view-chart-legend-color: #404040;--gts-classname-font-color: #004eff;--gts-labelname-font-color: #19A979;--gts-attrname-font-color: #ED4A7B;--gts-separator-font-color: #a0a0a0;--gts-labelvalue-font-color: #000000;--gts-attrvalue-font-color: #000000;--gts-stack-font-color: #000000;--gts-tree-expanded-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA7klEQVQ4T82TMW7CQBBF/0g+QOpINEkVCmpaLoBm5COk5QYoaeAY3MDSei2LGu4QKakiBA1tCpTK8kS2sLVe2xSh8XSrnf9m/s4s4c6gO/UYGEBEXlT1bK396bFGIjIJguA7iqJLkVNbYOZXItoQ0QHAzBhz9CCFeAVgCeAjy7Jpmqa/NUBEEgDzktqGuOKKO47j+KsGhGH4lOf5HsDIg5ycyqVYVd+steuGheLAzM9EtPMgW1VdVGWJ6N0YU1gpozVGH+K+gy/uBHR1crXUqNzbQXXhduJ69sd7cxOZ+UFVH5Mk+exb+YGt8n9+5h8up1sReYC0WAAAAABJRU5ErkJggg==);--gts-tree-collapsed-icon: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA0UlEQVQ4T6WTUW7CQAxEPQdozxYb9Qb94Aj9gQSoVCp6lMr21doDZFCQiFCU3YDY//d2PeOFPHnwJC+zAlVdA/jp+/6YmZ+1S0qCPxF5HUAAO3fvSpKS4ENEvm6gfUS0c5JiBma2Ibm/QiQPmbmdSqohquoA7GqSxRaapmkBjBkAeHP336t0UWBmHcnb+VcR4XcJpjDJLjPHkS4tleqZubmNiDHU6gumDQDYuvvh7hpV9V9EXgaA5Ka2jbMjmNk7yZOIfEfE8eFVfuSDLda4JDsD3FNdEckTC0YAAAAASUVORK5CYII=);--warp-view-popup-bg-color: #ffffff;--warp-view-popup-border-color: rgba(0, 0, 0, .2);--warp-view-popup-header-bg-color: #c0c0c0;--warp-view-popup-title-color: #404040;--warp-view-popup-close-color: #404040;--warp-view-popup-body-bg-color: #ffffff;--warp-view-popup-body-color: #000000;--warp-view-annotationtooltip-value-font-color: #004eff;--warp-view-annotationtooltip-font-color: #404040;--warp-view-spinner-color: #ff9900;--warp-view-tooltip-bg: #ffffff;--warp-view-tooltip-color: #000000;--warp-slider-connect-color: #ff9900;--warp-slider-handle-bg-color: #ffffff;--warp-slider-handle-color: #004eff;--warp-slider-handle-shadow: inset 0 0 1px #ffffff, inset 0 1px 7px #c0c0c0, 0 3px 6px -3px #a0a0a0}.noData{width:100%;text-align:center;color:var(--warp-view-chart-legend-color);position:relative}.js-plotly-plot .plotly .cursor-ew-resize{cursor:default!important}/*!\n * Copyright 2021 SenX S.A.S.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */.gts-classname{color:var(--gts-classname-font-color)}.gts-labelname{color:var(--gts-labelname-font-color)}.gts-attrname{color:var(--gts-attrname-font-color)}.gts-separator{color:var(--gts-separator-font-color)}.gts-labelvalue{color:var(--gts-labelvalue-font-color);font-style:italic}.gts-attrvalue{color:var(--gts-attrvalue-font-color);font-style:italic}:host{display:block}:host .expander{position:absolute;top:0;left:0;width:35px;z-index:9}:host #chartContainer{height:auto;position:relative;padding-top:30px}:host #chartContainer div.upperLine{position:absolute;top:0;left:0;height:0;border-bottom:1px solid var(--warp-view-chart-grid-color, #8e8e8e);right:10px}:host #chartContainer .annotation-wrapper{position:relative}:host .date{text-align:right;display:block;height:20px;vertical-align:middle;line-height:20px;position:absolute;top:0;left:40px}:host .chart{width:var(--warp-view-chart-width);height:var(--warp-view-chart-height)}:host .wv-tooltip{position:absolute;width:calc(100% - 50px);z-index:999;margin-left:10px;top:-1000px;font-size:10px}:host .wv-tooltip .tooltip-body{border:1px solid grey;border-radius:5px;background-color:var(--warp-view-tooltip-bg)!important;color:var(--warp-view-tooltip-color)!important;padding-left:10px;padding-right:10px;width:auto;max-width:100%;vertical-align:middle;line-height:10px;height:40px;overflow:visible;margin:1px}:host .wv-tooltip .tooltip-body .chip{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;cursor:pointer}:host .wv-tooltip .tooltip-body.trimmed{max-width:49%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body.full{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .wv-tooltip .tooltip-body .value{color:var(--warp-view-annotationtooltip-value-font-color)}:host .wv-tooltip .tooltip-body .tooltip-date{font-weight:700;text-align:left;display:block;width:100%;height:.8rem;padding-top:5px;padding-bottom:5px;vertical-align:middle;line-height:.8rem}:host .wv-tooltip .tooltip-body .round{border-radius:50%;background-color:#bbb;display:inline-block;width:5px;height:5px;border:2px solid #454545;margin-top:auto;margin-bottom:auto;vertical-align:middle;margin-right:5px}:host .wv-tooltip.left .tooltip-body{text-align:left;float:left}:host .wv-tooltip.left .tooltip-body .tooltip-date{text-align:left}:host .wv-tooltip.right .tooltip-body{float:right}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.SizeService }, { type: i0.NgZone }]; }, propDecorators: { type: [{ type: Input, args: ['type'] }], hiddenData: [{ type: Input, args: ['hiddenData'] }], standalone: [{ type: Input, args: ['standalone'] }], height: [{ type: Input, args: ['height'] }], pointHover: [{ type: Output, args: ['pointHover'] }], chartDraw: [{ type: Output, args: ['chartDraw'] }], boundsDidChange: [{ type: Output, args: ['boundsDidChange'] }], handleKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }, { type: HostListener, args: ['document:keydown', ['$event']] }], handleKeyup: [{ type: HostListener, args: ['keyup', ['$event']] }, { type: HostListener, args: ['document:keyup', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FycC12aWV3LWFubm90YXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvd2FycHZpZXctbmcvc3JjL2xpYi9lbGVtZW50cy93YXJwLXZpZXctYW5ub3RhdGlvbi93YXJwLXZpZXctYW5ub3RhdGlvbi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy93YXJwdmlldy1uZy9zcmMvbGliL2VsZW1lbnRzL3dhcnAtdmlldy1hbm5vdGF0aW9uL3dhcnAtdmlldy1hbm5vdGF0aW9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3JJLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBRXpELE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQyxPQUFPLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUVyQyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFFM0MsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQy9DLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUMxRCxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLHlCQUF5QixDQUFDOzs7Ozs7QUFTcEQsTUFBTSxPQUFPLDJCQUE0QixTQUFRLGlCQUFpQjtJQXdEaEUsWUFDUyxFQUFjLEVBQ2QsUUFBbUIsRUFDbkIsV0FB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