import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core'; import { PlotService, PlotType, PlotRequest, TagField, FilterDefaults, DataType, AxesTypes, PlotConfig, RenderOptions, RenderOptionsMap, Suggestion } from '../plot.service'; import { UntypedFormControl, } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; import { LimitByComponent } from '../limit-by/limit-by.component'; import { YAxisDefinitionComponent } from '../y-axis-definition/y-axis-definition.component'; import { QueryAutocompleteComponent } from '../query-autocomplete/query-autocomplete.component'; import { PlotViewComponent, LoadingEvent } from '../plot-view/plot-view.component'; import { GalleryViewComponent } from '../gallery-view/gallery-view.component'; import { WidgetDimensions } from '../dashboard.service'; @Component({ selector: 'pdb-visualization-page', templateUrl: './visualization-page.component.html', styleUrls: ['./visualization-page.component.scss'] }) export class VisualizationPageComponent implements OnInit, AfterViewInit { readonly DATE_PATTERN = "YYYY-MM-DD HH:mm:ss"; // for moment-JS @Input() defaultConfig?: PlotConfig; @Input() galleryEnabled = true; dateRange = new UntypedFormControl('2019-10-05 00:00:00 - 2019-10-11 23:59:59'); selectedPlotType = new Array(); plotTypes: PlotType[] = []; tagFields: Array = new Array(); groupBy = new Array(); @ViewChild('limitbycomponent') private limitbycomponent! : LimitByComponent; @ViewChild('y1AxisDefinitionComponent', { read: YAxisDefinitionComponent }) private y1AxisDefinitionComponent! : YAxisDefinitionComponent; @ViewChild('y2AxisDefinitionComponent', { read: YAxisDefinitionComponent }) private y2AxisDefinitionComponent! : YAxisDefinitionComponent; @ViewChild('query') query!: QueryAutocompleteComponent; @ViewChild('plotView') plotView!: PlotViewComponent; @ViewChild('galleryView') galleryView!: GalleryViewComponent; enableGallery = false; splitBy : TagField | undefined = undefined; y2AxisAvailable = false; intervalUnit = 'NO_INTERVAL'; intervalValue = 1; renderBarChartTickLabels = false; plotJobActive = false; constructor(private plotService: PlotService, private snackBar: MatSnackBar) { const params = new URLSearchParams(window.location.search); if (!this.defaultConfig && params.get("config")) { const config = JSON.parse(params.get("config")!); this.defaultConfig = config; } } showError(message:string) { this.snackBar.open(message, "", { duration: 5000, verticalPosition: 'top' }); } ngOnInit() { (window).initDatePicker(); this.plotTypes = this.plotService.getPlotTypes(); this.selectedPlotType.push(this.plotTypes[0]); this.plotService.getFilterDefaults().subscribe((filterDefaults: FilterDefaults) => { filterDefaults.fields.forEach((name:string) => { this.tagFields.push(new TagField(name)); }, (error: any) => { this.showError(error.error.message); }); const groupByDefaults = this.defaultConfig ? this.defaultConfig.groupBy : filterDefaults.groupBy; this.groupBy = this.tagFields.filter(val => groupByDefaults.includes(val.name)); this.splitBy = this.tagFields.find(val => filterDefaults.splitBy == val.name); if (this.defaultConfig) { this.plot(); } }); } ngAfterViewInit(): void { if (this.defaultConfig) { const c = this.defaultConfig; this.query.suggestionFetcherEnabled = false; this.query.queryField.setValue(new Suggestion(c.query, c.query, c.query.length)); this.query.suggestionFetcherEnabled = true; this.selectedPlotType = this.plotTypes.filter(pt => c.aggregates.includes(pt.id)); this.changePlotType(this.selectedPlotType); this.updateDateRange(c.dateRange, false); this.limitbycomponent.limitBy = c.limitBy; this.limitbycomponent.limit = c.limit; this.intervalUnit = c.intervalUnit; this.intervalValue = c.intervalValue; this.y1AxisDefinitionComponent.yAxisScale = c.y1.axisScale; this.y1AxisDefinitionComponent.minYValue = c.y1.rangeMin; this.y1AxisDefinitionComponent.maxYValue = c.y1.rangeMax; this.y1AxisDefinitionComponent.yAxisUnit = c.y1.rangeUnit; if (c.y2) { this.y2AxisDefinitionComponent.yAxisScale = c.y2.axisScale; this.y2AxisDefinitionComponent.minYValue = c.y2.rangeMin; this.y2AxisDefinitionComponent.maxYValue = c.y2.rangeMax; this.y2AxisDefinitionComponent.yAxisUnit = c.y2.rangeUnit; } } } toggleGallery(event: Event){ this.galleryView.show = this.enableGallery; } loading(event: LoadingEvent) { this.plotJobActive = event.loading; } updateDateRange(newDateRange: string, updatePlot=true) { (document.getElementById("search-date-range")).value = newDateRange; if (updatePlot){ this.plot(); } } changePlotType(selectedPlotTypes: Array) { const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(selectedPlotTypes)); this.plotTypes.forEach(pt => pt.active=false); compatiblePlotTypes.forEach(pt => pt.active=true); const axesTypes = this.getAxes(); this.y2AxisAvailable = axesTypes.y.length == 2; } selectedPlotTypesContains(plotTypeIds: Array){ return this.selectedPlotType.filter(pt => plotTypeIds.includes(pt.id)).length > 0; } dateRangeAsString() : string { return (document.getElementById("search-date-range")).value; } gallery(){ if (this.splitBy != null){ this.plotView.imageUrl = ''; this.plotView.stats = null; this.galleryView.show=true; const request = this.createPlotRequest(); this.galleryView.renderGallery(request, this.splitBy.name); } else { console.error("variable splitBy was null when rendering gallery"); } } getAxes() : AxesTypes { const x = new Array(); const y = new Array(); for(var i = 0; i < this.selectedPlotType.length; i++){ var plotType = this.selectedPlotType[i]; if (!x.includes(plotType.xAxis)) { x.push(plotType.xAxis); } if (!y.includes(plotType.yAxis)) { y.push(plotType.yAxis); } } return new AxesTypes(x,y); } abort() { this.plotService.abort((window).submitterId).subscribe({ complete: () => { } }); } plot(){ const config = this.createPlotConfig(); this.plotView.plot(config, this.plotDimensionSupplier); } plotDimensionSupplier(): WidgetDimensions{ const results = document.getElementById("results"); return new WidgetDimensions( results != null ? results.offsetWidth-1 : 1024, results != null ? results.offsetHeight-1: 1024); } createPlotConfig(): PlotConfig { const aggregates = new Array(); this.selectedPlotType.forEach(a => aggregates.push(a.id)); const y1 = this.y1AxisDefinitionComponent.getAxisDefinition(); const y2 = this.y2AxisDefinitionComponent ? this.y2AxisDefinitionComponent.getAxisDefinition() : undefined; const config = new PlotConfig( this.query.query, this.groupBy.map(o => o.name), this.limitbycomponent.limitBy, this.limitbycomponent.limit, y1, y2, this.dateRangeAsString(), // dateRange aggregates, // aggregates this.intervalUnit, this.intervalValue, this.renderBarChartTickLabels, ); return config; } createPlotRequest(): PlotRequest { const results = document.getElementById("results"); const config = this.createPlotConfig(); const renderOptions : RenderOptionsMap = { 'main': new RenderOptions(results!.offsetHeight-1, results!.offsetWidth-1, false, true), 'thumbnail': new RenderOptions(200, 300, false, false), }; const request = new PlotRequest( (window).submitterId, config, renderOptions ); return request; } serializedConfig(): string { try{ const config = this.createPlotConfig(); return JSON.stringify(config); }catch (e) { return ""; } } }