200 lines
6.0 KiB
TypeScript
200 lines
6.0 KiB
TypeScript
import { Injectable, OnInit } from '@angular/core';
|
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
|
import { Observable } from 'rxjs/Observable';
|
|
import { map } from 'rxjs/operators';
|
|
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class PlotService {
|
|
|
|
plotTypes: Array<PlotType>;
|
|
|
|
constructor(private http: HttpClient) {
|
|
this.plotTypes = new Array<PlotType>();
|
|
this.plotTypes.push(new PlotType("SCATTER","Scatter","scatter-chart2",true,DataType.Time,DataType.Duration));
|
|
this.plotTypes.push(new PlotType("HEATMAP", "Heatmap", "heatmap", false, DataType.Other, DataType.Other));
|
|
this.plotTypes.push(new PlotType("CONTOUR", "Contour", "contour-chart", false, DataType.Time, 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", "histogram", true, DataType.HistogramBin, DataType.HistogramCount));
|
|
this.plotTypes.push(new PlotType("RIDGELINES", "Ridgelines", "ridgelines", 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", "Parallel Requests", "parallel-requests-chart", true, DataType.Time, DataType.Count));
|
|
this.plotTypes.push(new PlotType("VIOLIN", "Violin", "violin-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", "pie-chart", false, DataType.Other, DataType.Other));
|
|
this.plotTypes.push(new PlotType("BAR", "Bar", "bar-chart", false, DataType.Other, DataType.Other));
|
|
this.plotTypes.push(new PlotType("STEP_FIT", "Step Fit", "step-fit", false, DataType.Other, DataType.Other));
|
|
this.plotTypes.push(new PlotType("LAG", "Lag", "lag-plot", false, DataType.Other, DataType.Other));
|
|
this.plotTypes.push(new PlotType("ACF", "ACF", "acf-plot", false, DataType.Other, DataType.Other));
|
|
}
|
|
|
|
ngOnInit() {
|
|
|
|
}
|
|
|
|
getPlotTypes(): Array<PlotType> {
|
|
return this.plotTypes.filter(plotType => plotType.active);
|
|
}
|
|
|
|
getTagFields(): Observable<Array<string>> {
|
|
return this.http.get<Array<string>>('//'+window.location.hostname+':8080/fields');
|
|
}
|
|
|
|
autocomplete(query: string, caretIndex: number, resultMode: ResultMode): Observable<AutocompleteResult>
|
|
{
|
|
const options = {
|
|
params: new HttpParams()
|
|
.set('caretIndex', ""+caretIndex)
|
|
.set('query', query)
|
|
.set('resultMode', resultMode)
|
|
};
|
|
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);
|
|
}
|
|
|
|
getFilterDefaults(): Observable<FilterDefaults>{
|
|
return this.http.get<FilterDefaults>('//'+window.location.hostname+':8080/filters/defaults')
|
|
}
|
|
|
|
splitQuery(query: string, splitBy:string) : Observable<Array<string>>{
|
|
|
|
const q = "("+query+") and "+splitBy+"=";
|
|
return this.autocomplete(q, q.length+1, ResultMode.FULL_VALUES).pipe(
|
|
map(
|
|
autocompleteResult => autocompleteResult.proposals.map(suggestion => suggestion.value)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
export class PlotType {
|
|
id: string;
|
|
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.icon = icon;
|
|
this.active = active;
|
|
this.xAxis = xAxis;
|
|
this.yAxis = yAxis;
|
|
}
|
|
|
|
compatible(other: PlotType) : boolean {
|
|
|
|
const xEqual = this.xAxis === other.xAxis;
|
|
const yEqual = this.yAxis === other.yAxis;
|
|
const anyIsOther = this.xAxis === DataType.Other
|
|
|| this.yAxis === DataType.Other
|
|
|| other.xAxis === DataType.Other
|
|
|| other.yAxis === DataType.Other;
|
|
|
|
var result = xEqual || yEqual;
|
|
|
|
// if either dimension is Other, then this plot is not compatible with any other plot
|
|
result = result && !anyIsOther;
|
|
|
|
// is not the same
|
|
result = result && this.name != other.name;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
export class TagField {
|
|
name: string;
|
|
|
|
constructor(name: string) {
|
|
this.name = name;
|
|
}
|
|
}
|
|
|
|
export enum DataType {
|
|
Time,
|
|
Duration,
|
|
Percent,
|
|
Count,
|
|
Group,
|
|
Metric,
|
|
HistogramBin,
|
|
HistogramCount,
|
|
Other
|
|
}
|
|
|
|
export class Suggestion {
|
|
value: string;
|
|
newQuery: string;
|
|
newCaretPosition: number;
|
|
}
|
|
|
|
|
|
export class AutocompleteResult{
|
|
proposals: Array<Suggestion>;
|
|
}
|
|
|
|
export class PlotRequest {
|
|
query : string;
|
|
height : number;
|
|
width : number;
|
|
thumbnailMaxWidth : number = 300;
|
|
thumbnailMaxHeight : number = 200;
|
|
groupBy : Array<string>;
|
|
limitBy : string;
|
|
axisScale : string;
|
|
limit : number;
|
|
dateRange : string;
|
|
aggregates : Array<string>;
|
|
yRangeMin : number;
|
|
yRangeMax : number;
|
|
yRangeUnit : string;
|
|
keyOutside : boolean = false;
|
|
generateThumbnail : boolean;
|
|
|
|
copy(): PlotRequest {
|
|
return JSON.parse(JSON.stringify(this));
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
export class FilterDefaults {
|
|
groupBy: Array<string>;
|
|
fields: Array<string>;
|
|
splitBy: string;
|
|
}
|
|
|
|
export enum ResultMode {
|
|
CUT_AT_DOT = "CUT_AT_DOT",
|
|
FULL_VALUES = "FULL_VALUES"
|
|
}
|