prepare sending of plot requests

- values for query and date range were not
  propagated to the model
This commit is contained in:
2019-10-26 10:32:11 +02:00
parent 7636781315
commit f235890cc1
7 changed files with 156 additions and 63 deletions

View File

@@ -15,22 +15,23 @@ export class PlotService {
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
this.plotTypes = new Array<PlotType>(); this.plotTypes = new Array<PlotType>();
this.plotTypes.push(new PlotType( this.plotTypes.push(new PlotType(
"SCATTER",
"Scatter", "Scatter",
"scatter-chart2", "scatter-chart2",
true, true,
DataType.Time, DataType.Time,
DataType.Duration)); DataType.Duration));
this.plotTypes.push(new PlotType("Heatmap", "heatmap", false, DataType.Other, DataType.Other)); this.plotTypes.push(new PlotType("HEATMAP", "Heatmap", "heatmap", false, DataType.Other, DataType.Other));
this.plotTypes.push(new PlotType("Contour", "contour-chart", false, DataType.Time, DataType.Duration)); this.plotTypes.push(new PlotType("CONTOUR", "Contour", "contour-chart", false, DataType.Time, DataType.Duration));
this.plotTypes.push(new PlotType("Cumulative Distribution", "cumulative-distribution-chart", true, DataType.Percent, DataType.Duration)); this.plotTypes.push(new PlotType("CUM_DISTRIBUTION", "Cumulative Distribution", "cumulative-distribution-chart", true, DataType.Percent, DataType.Duration));
this.plotTypes.push(new PlotType("Histogram", "histogram", false, DataType.Group, DataType.Duration)); this.plotTypes.push(new PlotType("HISTOGRAM", "Histogram", "histogram", false, DataType.Group, DataType.Duration));
this.plotTypes.push(new PlotType("Ridgelines", "ridgelines", false, DataType.Other, DataType.Other)); this.plotTypes.push(new PlotType("RIDGELINES", "Ridgelines", "ridgelines", false, DataType.Other, DataType.Other));
this.plotTypes.push(new PlotType("Quantile-Quantile", "quantile-quantile", false, DataType.Other, DataType.Other)); this.plotTypes.push(new PlotType("QQ", "Quantile-Quantile", "quantile-quantile", false, DataType.Other, DataType.Other));
this.plotTypes.push(new PlotType("Parallel Requests", "parallel-requests-chart", true, DataType.Time, DataType.Count)); this.plotTypes.push(new PlotType("PARALLEL", "Parallel Requests", "parallel-requests-chart", true, DataType.Time, DataType.Count));
this.plotTypes.push(new PlotType("Violin", "violin-chart", false, DataType.Group, DataType.Duration)); this.plotTypes.push(new PlotType("VIOLIN", "Violin", "violin-chart", false, DataType.Group, DataType.Duration));
this.plotTypes.push(new PlotType("Strip", "strip-chart", false, DataType.Group, DataType.Duration)); this.plotTypes.push(new PlotType("STRIP", "Strip", "strip-chart", false, DataType.Group, DataType.Duration));
this.plotTypes.push(new PlotType("Pie", "pie-chart", false, DataType.Other, DataType.Other)); this.plotTypes.push(new PlotType("PIE", "Pie", "pie-chart", false, DataType.Other, DataType.Other));
this.plotTypes.push(new PlotType("Bar", "bar-chart", false, DataType.Other, DataType.Other)); this.plotTypes.push(new PlotType("BAR", "Bar", "bar-chart", false, DataType.Other, DataType.Other));
this.tagFields = new Array<TagField>(); this.tagFields = new Array<TagField>();
} }
@@ -64,17 +65,25 @@ export class PlotService {
}; };
return this.http.get<AutocompleteResult>('//'+window.location.hostname+':8080/autocomplete', options); return this.http.get<AutocompleteResult>('//'+window.location.hostname+':8080/autocomplete', options);
} }
sendPlotRequest(plotRequest: PlotRequest): Observable<PlotResponse>{
console.log("send plot request: "+ JSON.stringify(plotRequest));
return this.http.post<PlotResponse>('//'+window.location.hostname+':8080/plots', plotRequest);
}
} }
export class PlotType { export class PlotType {
id: string;
name: string; name: string;
icon: string icon: string
active: boolean; active: boolean;
xAxis: DataType; xAxis: DataType;
yAxis: DataType; yAxis: DataType;
constructor(name: string, icon: string, active: boolean, xAxis: DataType, yAxis: DataType) { constructor(id: string, name: string, icon: string, active: boolean, xAxis: DataType, yAxis: DataType) {
this.id = id;
this.name = name; this.name = name;
this.icon = icon; this.icon = icon;
this.active = active; this.active = active;
@@ -131,6 +140,43 @@ export class AutocompleteResult{
proposals: Array<Suggestion>; proposals: Array<Suggestion>;
} }
export class PlotRequest {
query : string;
height : number;
width : number;
thumbnailMaxWidth : number = 300;
thumbnailMaxHeight : number = 200;
groupBy : Array<string>;
limitBy : string;
yAxis : string;
limit : number;
dateRange : string;
aggregates : Array<string>;
yRangeMin : number;
yRangeMax : number;
yRangeUnit : string;
keyOutside : boolean = false;
generateThumbnail : boolean;
}
export class PlotResponse {
imageUrl : string;
stats : PlotResponseStats;
thumbnailUrl : string;
}
export class PlotResponseStats {
maxValue : number;
values : number;
average : number ;
plottedValues : number;
dataSeriesStats : Array<DataSeriesStats>;
}
export class DataSeriesStats {
values : number;
maxValue : number;
average : number;
plottedValues : number;
}

View File

@@ -2,10 +2,10 @@
type="text" type="text"
id="query-autocomplete-input" id="query-autocomplete-input"
placeholder="Query" placeholder="Query"
[formControl]="query" [formControl]="queryField"
[matAutocomplete]="auto" [matAutocomplete]="auto"
(keyup)="onKey($event)" (keyup)="onKey($event)"
(focus)="onKey($event)"/> (mouseup)="onKey($event)"/>
<mat-autocomplete <mat-autocomplete
#auto="matAutocomplete" #auto="matAutocomplete"
[displayWith]="displaySuggestion" [displayWith]="displaySuggestion"

View File

@@ -1,7 +1,8 @@
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input, ViewChild } from '@angular/core';
import {FormControl} from '@angular/forms'; import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {startWith, map} from 'rxjs/operators'; import {startWith, map} from 'rxjs/operators';
import {MatAutocompleteTrigger } from '@angular/material/autocomplete';
import { PlotService, PlotType, AutocompleteResult, Suggestion } from '../plot.service'; import { PlotService, PlotType, AutocompleteResult, Suggestion } from '../plot.service';
@Component({ @Component({
@@ -11,38 +12,65 @@ import { PlotService, PlotType, AutocompleteResult, Suggestion } from '../plot.s
}) })
export class QueryAutocompleteComponent implements OnInit { export class QueryAutocompleteComponent implements OnInit {
@Input() query = new FormControl(''); queryField = new FormControl('');
suggestions = new FormControl(); suggestions = new FormControl();
filteredSuggestions: Observable<Suggestion[]>; filteredSuggestions: Observable<Suggestion[]>;
query : string;
@ViewChild(MatAutocompleteTrigger, {static: false})
autocomplete: MatAutocompleteTrigger;
constructor(private plotService: PlotService) {} constructor(private plotService: PlotService) {}
ngOnInit() { ngOnInit() {
const that = this;
this.query = "";
this.queryField.valueChanges.subscribe(function(value){
if (typeof value == "string") {
that.query = value;
}else{
that.query = value.newQuery;
var el : HTMLInputElement = <HTMLInputElement>document.getElementById('query-autocomplete-input');
el.selectionStart=value.newCaretPosition;
el.selectionEnd=value.newCaretPosition;
that.fetchSuggestions(value.newCaretPosition);
}
});
this.filteredSuggestions = this.suggestions.valueChanges.pipe( this.filteredSuggestions = this.suggestions.valueChanges.pipe(
map(value => value) map(value => value)
); );
} }
onKey(event: any) { onKey(event: any) {
const that = this; //console.log(event);
console.log(event);
if (event.key == "ArrowDown" || event.key == "ArrowUp"){ if (event.key == "ArrowDown" || event.key == "ArrowUp"){
return; return;
} }
const query = typeof this.query.value == "string"
? this.query.value
: this.query.value.newQuery;
const caretIndex = event.srcElement.selectionStart +1; const caretIndex = event.srcElement.selectionStart +1;
this.fetchSuggestions(caretIndex);
}
fetchSuggestions(caretIndex: number){
const that = this;
const query = typeof this.queryField.value == "string"
? this.queryField.value
: this.queryField.value.newQuery;
this.plotService this.plotService
.autocomplete(query, caretIndex) .autocomplete(query, caretIndex)
.subscribe( .subscribe(
(data: AutocompleteResult) => {// success path (data: AutocompleteResult) => {// success path
console.log(JSON.stringify(data.proposals)); //console.log(JSON.stringify(data.proposals));
that.suggestions.setValue(data.proposals); that.suggestions.setValue(data.proposals);
that.autocomplete.openPanel();
}, },
error => console.log(error) error => console.log(error)
); );

View File

@@ -1,18 +1,19 @@
<div id="visualization"> <div id="visualization">
<div id="query-box"> <div id="query-box">
<pdb-query-autocomplete ></pdb-query-autocomplete> <pdb-query-autocomplete #query></pdb-query-autocomplete>
</div> </div>
<div id="filters"> <div id="filters">
<div id="filterpanel"> <div id="filterpanel">
<mat-form-field class="mat-field-full-width"> <mat-form-field class="mat-field-full-width">
<mat-label>Date Range:</mat-label> <mat-label>Date Range:</mat-label>
<input matInput [formControl]="dateRange" name="dates" /> <input matInput id="search-date-range" value="dateRange" name="dates" (input)="changeDate($event)" />
<input type="hidden" id="hidden-search-date-range" [(ngModel)]="hiddenSearchDateRange" />
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-field-full-width"> <mat-form-field class="mat-field-full-width">
<mat-label>Type:</mat-label> <mat-label>Type:</mat-label>
<mat-select [formControl]="selectedPlotType"> <mat-select [formControl]="selectedPlotType">
<mat-option *ngFor="let plotType of plotTypes" [value]="plotType.name"> <mat-option *ngFor="let plotType of plotTypes" [value]="plotType">
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}} <img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
</mat-option> </mat-option>
</mat-select> </mat-select>
@@ -20,9 +21,9 @@
<mat-form-field> <mat-form-field>
<mat-label>Combine with:</mat-label> <mat-label>Combine with:</mat-label>
<mat-select [(value)]="selectedCombinePlotType"> <mat-select [formControl]="selectedCombinePlotType">
<mat-option>-</mat-option> <mat-option>-</mat-option>
<mat-option *ngFor="let plotType of combinePlotTypes" [value]="plotType.name"> <mat-option *ngFor="let plotType of combinePlotTypes" [value]="plotType">
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}} <img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
</mat-option> </mat-option>
</mat-select> </mat-select>

View File

@@ -1,9 +1,10 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { PlotService, PlotType } from '../plot.service'; import { PlotService, PlotType, PlotRequest, PlotResponse } from '../plot.service';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { FormControl, Validators } from '@angular/forms'; import { FormControl, Validators } from '@angular/forms';
import { LimitByComponent } from '../limit-by/limit-by.component'; import { LimitByComponent } from '../limit-by/limit-by.component';
import { YAxisRangeComponent } from '../y-axis-range/y-axis-range.component'; import { YAxisRangeComponent } from '../y-axis-range/y-axis-range.component';
import { QueryAutocompleteComponent } from '../query-autocomplete/query-autocomplete.component';
@Component({ @Component({
@@ -35,7 +36,8 @@ export class VisualizationPageComponent implements OnInit {
@ViewChild(YAxisRangeComponent, {static: false}) @ViewChild(YAxisRangeComponent, {static: false})
private yAxisRangeComponent : YAxisRangeComponent; private yAxisRangeComponent : YAxisRangeComponent;
query: string; @ViewChild(QueryAutocompleteComponent, {static: false})
query: QueryAutocompleteComponent;
enableGallery = false; enableGallery = false;
@@ -48,9 +50,8 @@ export class VisualizationPageComponent implements OnInit {
ngOnInit() { ngOnInit() {
const that = this; const that = this;
this.query = "pod=*";
this.plotTypes = this.plotService.getPlotTypes(); this.plotTypes = this.plotService.getPlotTypes();
this.selectedPlotType.setValue(this.plotTypes[0].name); this.selectedPlotType.setValue(this.plotTypes[0]);
this.plotTypes.forEach(pt => this.availablePlotTypes[pt.name] = pt); this.plotTypes.forEach(pt => this.availablePlotTypes[pt.name] = pt);
@@ -59,17 +60,21 @@ export class VisualizationPageComponent implements OnInit {
this.tagFields = this.plotService.getTagFields(); this.tagFields = this.plotService.getTagFields();
this.yAxis = "log"; this.yAxis = "log";
this.selectedPlotType.valueChanges.subscribe(function(selectedMainPlotType){ this.selectedPlotType.valueChanges.subscribe(function(selectedMainPlotType){
that.combinePlotTypes = that.getCombinablePlotTypes(selectedMainPlotType); that.combinePlotTypes = that.getCombinablePlotTypes(selectedMainPlotType);
if (!that.combinePlotTypes.includes(that.selectedCombinePlotType.value)){
that.selectedCombinePlotType.setValue('');
}
}); });
} }
changeDate(event){
console.log("changed date: " + JSON.stringify(event));
}
getCombinablePlotTypes(selectedMainPlotType) : Array<any>{ getCombinablePlotTypes(selectedMainPlotType) : Array<any>{
const mainPlotType = this.availablePlotTypes[selectedMainPlotType]; //const mainPlotType = this.availablePlotTypes[selectedMainPlotType];
const mainPlotType = selectedMainPlotType;
const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(mainPlotType)); const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(mainPlotType));
return compatiblePlotTypes; return compatiblePlotTypes;
@@ -77,23 +82,32 @@ export class VisualizationPageComponent implements OnInit {
plot(){ plot(){
var request = {}; var aggregates = [];
request['query'] = this.query; aggregates.push(this.selectedPlotType.value.id);
request['height'] = document.getElementById("results").offsetHeight; if (this.selectedCombinePlotType.value){
request['width'] = document.getElementById("results").offsetWidth; aggregates.push(this.selectedCombinePlotType.value.id);
request['groupBy'] = this.groupBy.map(o => o.name); }
request['limitBy'] = this.limitbycomponent.limitBy;
request['limit'] = this.limitbycomponent.limit;
request['dateRange'] = this.dateRange.value;
request['axisScale'] = this.yAxis;
request['aggregate'] = this.selectedCombinePlotType.value;
request['keyOutside'] = false;
request['generateThumbnail'] = this.enableGallery;
request['yRangeMin'] = this.yAxisRangeComponent.minYValue;
request['yRangeMax'] = this.yAxisRangeComponent.maxYValue;
request['yRangeUnit'] = this.yAxisRangeComponent.yAxisUnit;
console.log("plot clicked: "+ JSON.stringify(request)); var request = new PlotRequest();
request.query = this.query.query;
request.height = document.getElementById("results").offsetHeight;
request.width = document.getElementById("results").offsetWidth;
request.groupBy = this.groupBy.map(o => o.name);
request.limitBy = this.limitbycomponent.limitBy;
request.limit = this.limitbycomponent.limit;
request.dateRange = (<HTMLInputElement>document.getElementById("search-date-range")).value;
request.yAxis = this.yAxis;
request.aggregates = aggregates;
request.keyOutside = false;
request.generateThumbnail = this.enableGallery;
request.yRangeMin = this.yAxisRangeComponent.minYValue;
request.yRangeMax = this.yAxisRangeComponent.maxYValue;
request.yRangeUnit = this.yAxisRangeComponent.yAxisUnit;
this.plotService.sendPlotRequest(request).subscribe(function(plotResponse){
console.log("response: " + JSON.stringify(plotResponse));
});
} }
} }

View File

@@ -43,6 +43,10 @@
}, },
}); });
$('#search-date-range').on('apply.daterangepicker', function(ev, picker) {
const range = $('#search-date-range').val();
console.log("update date range: " + range);
});
}); });
</script> </script>
</body> </body>