UNPKG

@senx/warpview

Version:
565 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, Input, NgZone, Output, Renderer2, ViewChild, ViewEncapsulation } from '@angular/core'; import { GTSLib } from '../../utils/gts.lib'; import { ChartBounds } from '../../model/chartBounds'; import { ColorLib } from '../../utils/color-lib'; import { WarpViewComponent } from '../warp-view-component'; import { SizeService } from '../../services/resize.service'; import { Logger } from '../../utils/logger'; import { Subject } from 'rxjs'; import { throttleTime } from 'rxjs/operators'; import { ChartLib } from '../../utils/chart-lib'; 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 WarpViewChartComponent 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.standalone = true; this.boundsDidChange = new EventEmitter(); this.pointHover = new EventEmitter(); this.warpViewChartResize = new EventEmitter(); // tslint:disable-next-line:variable-name this._type = 'line'; this.visibility = []; this.maxTick = 0; this.minTick = 0; this.visibleGtsId = []; this.gtsId = []; this.dataHashset = {}; this.chartBounds = new ChartBounds(); this.visibilityStatus = 'unknown'; this.afterBoundsUpdate = false; this.maxPlottable = 10000; this.parsing = false; this.unhighliteCurve = new Subject(); this.highliteCurve = new Subject(); this.layout = { legend: { orientation: 'h', y: -0.3 }, showlegend: false, autosize: true, hovermode: 'x', hoverdistance: 20, xaxis: { font: {} }, yaxis: { exponentformat: 'none', fixedrange: true, automargin: true, showline: true, font: {} }, margin: { t: 0, b: 40, r: 10, l: 50 }, }; this.LOG = new Logger(WarpViewChartComponent, this._debug); } 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, this._hiddenData); 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', visible, hidden); } } set type(type) { this._type = type; this.drawChart(); } update(options, refresh) { this.drawChart(refresh); } ngOnInit() { this._options = this._options || this.defOptions; } async getTimeClip() { return new Promise(resolve => { this.LOG.debug(['getTimeClip'], this.chartBounds); resolve(this.chartBounds); }); } resize(layout) { if (!!layout) { this.LOG.debug(['resize'], layout); this.height = layout.height; this.layout.height = this.height; if (this._options.showRangeSelector) { this.layout.xaxis.rangeslider = { bgcolor: 'transparent', thickness: 40 / this.height }; } } } drawChart(reparseNewData = false) { this.LOG.debug(['drawChart', 'this.layout', 'this.options'], this.layout, this._options, (this._options.bounds || {}).minDate); if (!this.initChart(this.el, false, false, reparseNewData)) { this.LOG.debug(['drawChart', 'initChart', 'empty'], this._options); return; } this.plotlyConfig.scrollZoom = true; this.layout.yaxis.gridcolor = this.getGridColor(this.el.nativeElement); this.layout.xaxis.gridcolor = this.getGridColor(this.el.nativeElement); this.layout.yaxis.zerolinecolor = this.getGridColor(this.el.nativeElement); this.layout.xaxis.zerolinecolor = this.getGridColor(this.el.nativeElement); this.layout.margin.t = this.standalone ? 20 : 10; if (!this._responsive) { this.layout.width = this.width; this.layout.height = this.height; } this.LOG.debug(['drawChart', 'this.options'], this.layout, this._options); this.LOG.debug(['drawChart', 'this.layout'], this.layout); this.LOG.debug(['drawChart', 'this.plotlyConfig'], this.plotlyConfig); if (!!this._options.showRangeSelector) { this.resize({ height: this.height, width: 0 }); } else { this.layout.margin.b = 30; } this.layout.showlegend = !!this._options.showlegend; this.layout = { ...this.layout }; this.highliteCurve.pipe(throttleTime(200)).subscribe(value => { this.graph.restyleChart({ opacity: 0.4 }, value.off); this.graph.restyleChart({ opacity: 1 }, value.on); }); this.unhighliteCurve.pipe(throttleTime(200)).subscribe(value => { this.graph.restyleChart({ opacity: 1 }, value); }); this.loading = false; } emitNewBounds(min, max, marginLeft) { this.LOG.debug(['emitNewBounds'], min, max); this.boundsDidChange.emit({ bounds: { min, max, marginLeft }, source: 'chart' }); } initChart(el, resize = true, customData = false, firstDraw = false) { const res = super.initChart(el); const x = { tick0: undefined, range: [] }; this.LOG.debug(['initChart', 'updateBounds'], this.chartBounds, this._options.bounds); const min = (this._options.bounds || {}).minDate || this.chartBounds.tsmin || this.minTick; const max = (this._options.bounds || {}).maxDate || this.chartBounds.tsmax || this.maxTick; this.LOG.debug(['initChart', 'updateBounds'], [min, max]); const pad = ChartLib.fraction2r(this.minTick, this.maxTick, 0.067); if (this._options.timeMode && this._options.timeMode === 'timestamp') { x.tick0 = min - pad; x.range = [x.tick0, max + pad]; } else { x.tick0 = GTSLib.toISOString(min - pad, this.divider, this._options.timeZone); x.range = [x.tick0, GTSLib.toISOString(max + pad, this.divider, this._options.timeZone)]; } this.layout.xaxis = x; if (!!res) { this.resize({ height: this.height, width: 0 }); } return res; } convert(data, firstDraw = false) { this.parsing = !this._options.isRefresh; this.chartBounds.tsmin = undefined; this.chartBounds.tsmax = undefined; const dataset = []; this.LOG.debug(['convert'], this._options.timeMode); this.LOG.debug(['convert', 'this._hiddenData'], this._hiddenData); this.LOG.debug(['convert', 'this._options.timezone'], this._options.timeZone); if (GTSLib.isArray(data.data)) { let gtsList = GTSLib.flatDeep(GTSLib.flattenGtsIdArray(data.data, 0).res); this.maxTick = Number.MIN_VALUE; this.minTick = Number.MAX_VALUE; this.visibleGtsId = []; this.gtsId = []; const nonPlottable = gtsList.filter(g => (g.v && !GTSLib.isGtsToPlot(g))); gtsList = gtsList.filter(g => g.v && GTSLib.isGtsToPlot(g)); // initialize visibility status if (this.visibilityStatus === 'unknown') { this.visibilityStatus = gtsList.length > 0 ? 'plottableShown' : 'nothingPlottable'; } 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'; } const gtsCount = gtsList.length; for (let i = 0; i < gtsCount; i++) { const gts = gtsList[i]; if (gts.v && GTSLib.isGtsToPlot(gts)) { // Timsort.sort(gts.v, (a, b) => a[0] - b[0]); 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 type = ((data.params || [])[i] || { type: this._type }).type || this._type; const series = { type: type === 'spline' ? 'scatter' : 'scattergl', mode: type === 'scatter' || size <= 1 ? 'markers' : size > this.maxPlottable ? 'lines' : 'lines+markers', name: label, text: label, x: [], y: [], line: { color }, hoverinfo: 'none', connectgaps: false, visible: !(this._hiddenData.filter(h => h === gts.id).length > 0), }; if (size < this.maxPlottable) { series.marker = { size: 3, color: new Array(size).fill(color), line: { color, width: 3 }, opacity: new Array(size).fill(this._type === 'scatter' || size <= 1 || this._options.showDots ? 1 : 0) }; } switch (type) { case 'spline': series.line.shape = 'spline'; break; case 'area': series.fill = 'tozeroy'; series.fillcolor = ColorLib.transparentize(color, 0.3); break; case 'step': series.line.shape = 'hvh'; break; case 'step-before': series.line.shape = 'vh'; break; case 'step-after': series.line.shape = 'hv'; break; } this.visibleGtsId.push(gts.id); this.gtsId.push(gts.id); // this.LOG.debug(['convert'], 'forEach value'); const ticks = gts.v.map(t => t[0]); const values = gts.v.map(t => t[t.length - 1]); if (size > 0) { for (let v = 1; v < size; v++) { const ts = ticks[v]; this.minTick = ts <= this.minTick ? ts : this.minTick; this.maxTick = ts >= this.maxTick ? ts : 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)); } series.y = values; dataset.push(series); } } if (nonPlottable.length > 0 && gtsList.length === 0) { nonPlottable.forEach(g => { g.v.forEach(value => { const ts = value[0]; this.minTick = ts <= this.minTick ? ts : this.minTick; this.maxTick = ts >= this.maxTick ? ts : this.maxTick; }); }); // 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); } } } this.LOG.debug(['convert'], 'end', dataset, this.minTick, this.maxTick, GTSLib.toISOString(this.minTick, this.divider, this._options.timeZone), GTSLib.toISOString(this.maxTick, this.divider, this._options.timeZone)); this.noData = dataset.length === 0; this.parsing = false; return dataset; } afterPlot(plotlyInstance) { super.afterPlot(plotlyInstance); this.marginLeft = parseInt(this.graph.plotEl.nativeElement.querySelector('g.bglayer > rect').getAttribute('x'), 10); this.LOG.debug(['afterPlot', 'marginLeft'], this.marginLeft); if (this.chartBounds.tsmin !== this.minTick || this.chartBounds.tsmax !== this.maxTick) { this.chartBounds.tsmin = this.minTick; this.chartBounds.tsmax = this.maxTick; this.chartBounds.marginLeft = this.marginLeft; this.chartDraw.emit(this.chartBounds); if (this.afterBoundsUpdate || this.standalone) { this.LOG.debug(['afterPlot', 'updateBounds'], this.minTick, this.maxTick, this.afterBoundsUpdate); this.emitNewBounds(this.minTick, this.maxTick, this.marginLeft); this.loading = false; this.afterBoundsUpdate = false; } } else { this.loading = false; } } relayout(data) { let change = false; 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]']); 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.chartBounds); this.LOG.debug(['relayout', 'updateBounds'], GTSLib.toISOString(this.chartBounds.tsmin, this.divider, this._options.timeZone)); if (this._options.timeMode && this._options.timeMode === 'timestamp') { this.emitNewBounds(this.chartBounds.msmin, this.chartBounds.msmax, this.marginLeft); } else { this.emitNewBounds(this.chartBounds.tsmin, this.chartBounds.tsmax, this.marginLeft); } } this.loading = false; this.afterBoundsUpdate = true; this.chartDraw.emit(); } sliderChange($event) { this.LOG.debug(['sliderChange'], $event); } updateBounds(min, max) { this.LOG.debug(['updateBounds'], min, max, this._options); 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 = { ...this.layout }; this.LOG.debug(['updateBounds'], { ...this.layout.xaxis.range }); this.afterBoundsUpdate = true; } setRealBounds(chartBounds) { this.minTick = chartBounds.tsmin; this.maxTick = chartBounds.tsmax; this._options.bounds = this._options.bounds || {}; 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 }; } hover(data) { const xaxis = data.points[0].xaxis; const yaxis = data.points[0].yaxis; let toHighlight; const curves = []; let delta = Number.MAX_VALUE; let point; const annotations = []; data.points.forEach(p => { curves.push(p.curveNumber); /* annotations.push({ x: p.x, y: p.y, arrowhead: 6, arrowsize: 1, ax: 3, ay: 3, arrowcolor: p.data.line.color });*/ const dist = Math.abs(data.yvals[0] - p.y); if (delta > dist) { delta = dist; toHighlight = p.curveNumber; point = p; data.meta = { x: p.x, y: p.y.toPrecision(3), w: xaxis.l2p(p.x), h: yaxis.l2p(p.y), name: p.data.text }; } }); if (!!this.hoverTimeout) { clearTimeout(this.hoverTimeout); } /*this.graph.relayoutPlot('annotations', 'remove'); this.graph.relayoutPlot('annotations', annotations);*/ super.hover(data, toHighlight); } unhover(data) { super.unhover(data); if (!!this.hoverTimeout) { clearTimeout(this.hoverTimeout); } } handleMouseMove(evt) { evt.preventDefault(); if (this.standalone && this.line && !this.noData) { this.line.nativeElement.style.left = Math.max(evt.offsetX, 50) + 'px'; } } handleMouseEnter(evt) { evt.preventDefault(); this.marginLeft = this.marginLeft || this.el.nativeElement.getBoundingClientRect().left; if (this.standalone && this.line && !this.noData) { const h = this.graph.getElement('.draglayer')[0].getBoundingClientRect().height - 60; this.renderer.setStyle(this.line.nativeElement, 'height', h + 'px'); this.renderer.setStyle(this.line.nativeElement, 'display', 'block'); this.renderer.setStyle(this.line.nativeElement, 'bottom', (40 / this.height) + 'px'); } } queryShadow([firstShadowSelector, ...restOfTheShadowSelectors], itemSelector) { const reduceFunction = (currShadow, nextShadowSelector) => currShadow.shadowRoot.querySelector(nextShadowSelector); const firstShadow = document.querySelector(firstShadowSelector); const lastShadow = restOfTheShadowSelectors.reduce(reduceFunction, firstShadow); return lastShadow && lastShadow.querySelector(itemSelector); } handleMouseOut(evt) { // evt.preventDefault(); if (this.standalone && this.line && !this.noData) { this.renderer.setStyle(this.line.nativeElement, 'left', '-100px'); this.renderer.setStyle(this.line.nativeElement, 'display', 'none'); } if (!!this.hoverTimeout) { clearTimeout(this.hoverTimeout); } // setTimeout(() => this.graph.relayoutPlot('annotations', 'remove'), 1000); } } WarpViewChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: WarpViewChartComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.SizeService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); WarpViewChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.1", type: WarpViewChartComponent, selector: "warpview-chart", inputs: { hiddenData: "hiddenData", type: "type", standalone: "standalone" }, outputs: { boundsDidChange: "boundsDidChange", pointHover: "pointHover", warpViewChartResize: "warpViewChartResize" }, viewQueries: [{ propertyName: "line", first: true, predicate: ["line"], descendants: true }], 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\n<div id=\"chartContainer\" #chartContainer (mouseleave)=\"hideTooltip()\">\n <warpview-spinner *ngIf=\"loading\" message=\"Parsing data\"></warpview-spinner>\n <p class=\"noData\" *ngIf=\"noData\">No data to display</p>\n <p class=\"noData\" *ngIf=\"parsing\">Parsing data</p>\n <div *ngIf=\"!loading && !noData\" (mouseleave)=\"handleMouseOut($event)\"\n (mousemove)=\"handleMouseMove($event)\"\n (mouseenter)=\"handleMouseEnter($event)\">\n <div class=\"bar\" #line [ngClass]=\"{'full': !_options.showRangeSelector }\"></div>\n <warpview-plotly #graph\n [data]=\"plotlyData\" [layout]=\"layout\" [config]=\"plotlyConfig\"\n (afterPlot)=\"afterPlot($event)\"\n (relayout)=\"relayout($event)\" (hover)=\"hover($event)\"\n [updateOnLayoutChange]=\"true\" [updateOnDataChange]=\"true\" [debug]=\"debug\"\n (sliderChange)=\"sliderChange($event)\" (unhover)=\"unhover($event)\"\n [style]=\"{position: 'relative', width: '100%', height: '100%'}\"></warpview-plotly>\n </div>\n <div #toolTip class=\"wv-tooltip\"></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}.wv-tooltip{background-color:var(--warp-view-tooltip-bg)!important;color:var(--warp-view-tooltip-color)!important;text-align:left;position:absolute;display:none;padding:10px;border:1px solid grey;border-radius:5px;box-shadow:none;pointer-events:none;font-size:10px;min-width:100px;width:auto;max-width:50%;z-index:999;height:auto!important;left:-1000px}.wv-tooltip .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{display:block;height:100%}:host #chartContainer{height:100%}:host #chartContainer div{height:100%}:host .bar{width:1px;left:-100px;position:absolute;background-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;top:30px;bottom:55px;overflow:hidden;display:none;z-index:0;pointer-events:none;border-left:dashed 1px var(--warp-view-bar-color)}:host div.chart{width:var(--warp-view-chart-width);height:var(--warp-view-chart-height)}:host .executionErrorText{color:red;padding:10px;border-color:red;border-width:2px;border-radius:3px;border-style:solid;background:antiquewhite;position:absolute;top:-30px}\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.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], encapsulation: i0.ViewEncapsulation.ShadowDom }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: WarpViewChartComponent, decorators: [{ type: Component, args: [{ selector: 'warpview-chart', 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\n<div id=\"chartContainer\" #chartContainer (mouseleave)=\"hideTooltip()\">\n <warpview-spinner *ngIf=\"loading\" message=\"Parsing data\"></warpview-spinner>\n <p class=\"noData\" *ngIf=\"noData\">No data to display</p>\n <p class=\"noData\" *ngIf=\"parsing\">Parsing data</p>\n <div *ngIf=\"!loading && !noData\" (mouseleave)=\"handleMouseOut($event)\"\n (mousemove)=\"handleMouseMove($event)\"\n (mouseenter)=\"handleMouseEnter($event)\">\n <div class=\"bar\" #line [ngClass]=\"{'full': !_options.showRangeSelector }\"></div>\n <warpview-plotly #graph\n [data]=\"plotlyData\" [layout]=\"layout\" [config]=\"plotlyConfig\"\n (afterPlot)=\"afterPlot($event)\"\n (relayout)=\"relayout($event)\" (hover)=\"hover($event)\"\n [updateOnLayoutChange]=\"true\" [updateOnDataChange]=\"true\" [debug]=\"debug\"\n (sliderChange)=\"sliderChange($event)\" (unhover)=\"unhover($event)\"\n [style]=\"{position: 'relative', width: '100%', height: '100%'}\"></warpview-plotly>\n </div>\n <div #toolTip class=\"wv-tooltip\"></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}.wv-tooltip{background-color:var(--warp-view-tooltip-bg)!important;color:var(--warp-view-tooltip-color)!important;text-align:left;position:absolute;display:none;padding:10px;border:1px solid grey;border-radius:5px;box-shadow:none;pointer-events:none;font-size:10px;min-width:100px;width:auto;max-width:50%;z-index:999;height:auto!important;left:-1000px}.wv-tooltip .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{display:block;height:100%}:host #chartContainer{height:100%}:host #chartContainer div{height:100%}:host .bar{width:1px;left:-100px;position:absolute;background-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;top:30px;bottom:55px;overflow:hidden;display:none;z-index:0;pointer-events:none;border-left:dashed 1px var(--warp-view-bar-color)}:host div.chart{width:var(--warp-view-chart-width);height:var(--warp-view-chart-height)}:host .executionErrorText{color:red;padding:10px;border-color:red;border-width:2px;border-radius:3px;border-style:solid;background:antiquewhite;position:absolute;top:-30px}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.SizeService }, { type: i0.NgZone }]; }, propDecorators: { line: [{ type: ViewChild, args: ['line'] }], hiddenData: [{ type: Input, args: ['hiddenData'] }], type: [{ type: Input, args: ['type'] }], standalone: [{ type: Input, args: ['standalone'] }], boundsDidChange: [{ type: Output, args: ['boundsDidChange'] }], pointHover: [{ type: Output, args: ['pointHover'] }], warpViewChartResize: [{ type: Output, args: ['warpViewChartResize'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FycC12aWV3LWNoYXJ0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3dhcnB2aWV3LW5nL3NyYy9saWIvZWxlbWVudHMvd2FycC12aWV3LWNoYXJ0L3dhcnAtdmlldy1jaGFydC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy93YXJwdmlldy1uZy9zcmMvbGliL2VsZW1lbnRzL3dhcnAtdmlldy1jaGFydC93YXJwLXZpZXctY2hhcnQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxFQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQVUsTUFBTSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFHMUksT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQzNDLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDL0MsT0FBTyxFQUFrQixpQkFBaUIsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQzFFLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUMxRCxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUMsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDOzs7Ozs7QUFTL0MsTUFBTSxPQUFPLHNCQUF1QixTQUFRLGlCQUFpQjtJQTRGM0QsWUFD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QWEsQ0FBQyxDQUFDO1FBQzNFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNyQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1lBQy9CLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7U0FDbEM7UUFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxjQUFjLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxRSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxhQUFhLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLEdBQUcsQ0FBQ