diff --git a/pdb-js/src/app/dashboard-page/dashboard/plot-widget/plot-widget.component.ts b/pdb-js/src/app/dashboard-page/dashboard/plot-widget/plot-widget.component.ts
index c6ca11f..56c1ca0 100644
--- a/pdb-js/src/app/dashboard-page/dashboard/plot-widget/plot-widget.component.ts
+++ b/pdb-js/src/app/dashboard-page/dashboard/plot-widget/plot-widget.component.ts
@@ -1,8 +1,9 @@
import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
-import { PlotWidget, PlotWidgetRenderData } from 'src/app/dashboard.service';
+import { PlotSize, PlotWidget, PlotWidgetRenderData } from 'src/app/dashboard.service';
import { PlotViewComponent } from 'src/app/plot-view/plot-view.component';
-import { PlotRequest, PlotResponse, PlotService, RenderOptions } from 'src/app/plot.service';
+import { PlotConfig, PlotRequest, PlotResponse, PlotService, RenderOptions } from 'src/app/plot.service';
+import { AddPlotDialogComponent } from '../add-plot-dialog/add-plot-dialog.component';
import { FullScreenPlotDialogComponent } from '../full-screen-plot-dialog/full-screen-plot-dialog.component';
@Component({
@@ -19,7 +20,7 @@ export class PlotWidgetComponent implements AfterViewInit {
@ViewChild("plotView") plotView!: PlotViewComponent;
- constructor(private dialog: MatDialog, ){}
+ constructor(private dialog: MatDialog, private service: PlotService){}
ngAfterViewInit(): void {
@@ -44,4 +45,31 @@ export class PlotWidgetComponent implements AfterViewInit {
});
}
+
+
+
+ edit() {
+ this.dialog.open(AddPlotDialogComponent, {
+ data: {config: this.data.widget.config, title:"Edit Plot"},
+ width: 'calc(100% - 15px)',
+ height: 'calc(100% - 15px)',
+ }).afterClosed().subscribe((config?: PlotConfig) => {
+ if (config !== undefined && config.query.length > 0) {
+ this.data.widget.config = config;
+
+ this.isError = false;
+ this.data.plotResponse = undefined;
+
+ const request = PlotWidget.createPlotRequest(this.data.widget);
+ this.service.sendPlotRequest(request).subscribe({
+ next: (response: PlotResponse)=> {
+ this.data.plotResponse = response;
+ },
+ error: (error:any)=> {
+ this.isError = true;
+ },
+ });
+ }
+ });
+ }
}
diff --git a/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.html b/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.html
index dacad21..f4d3b5b 100644
--- a/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.html
+++ b/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.html
@@ -1,3 +1,8 @@
+
Create a new dashboard
diff --git a/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.scss b/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.scss
deleted file mode 100644
index 59b9cec..0000000
--- a/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-
-div[mat-dialog-content] {
- overflow: hidden;
-}
\ No newline at end of file
diff --git a/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.ts b/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.ts
index e660232..faeabf4 100644
--- a/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.ts
+++ b/pdb-js/src/app/dashboard-page/new-dashboard/new-dashboard.component.ts
@@ -1,11 +1,10 @@
import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
-import {MatDialog, MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
+import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import { DashboardCreationData } from 'src/app/dashboard.service';
@Component({
selector: 'app-new-dashboard',
- templateUrl: './new-dashboard.component.html',
- styleUrls: ['./new-dashboard.component.scss']
+ templateUrl: './new-dashboard.component.html'
})
export class NewDashboardComponent implements OnInit {
diff --git a/pdb-js/src/app/dashboard.service.ts b/pdb-js/src/app/dashboard.service.ts
index 14ab4de..8a55b05 100644
--- a/pdb-js/src/app/dashboard.service.ts
+++ b/pdb-js/src/app/dashboard.service.ts
@@ -1,7 +1,7 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
-import { PlotConfig, PlotResponse } from './plot.service';
+import { PlotConfig, PlotRequest, PlotResponse, RenderOptions } from './plot.service';
@Injectable({
providedIn: 'root'
@@ -67,6 +67,47 @@ export class PlotWidget extends BaseWidget {
constructor(override id: string, override size: 'SMALL'|'MEDIUM'|'LARGE', public config: PlotConfig) {
super(id, 'PLOT', size);
}
+
+ public static createPlotRequest(widget: PlotWidget): PlotRequest {
+
+ const height = this.height(widget.size);
+ const width = this.width(widget.size);
+
+ const fullWidth = window.innerWidth-30;
+ const fullHeight = window.innerHeight-30;
+
+ const request = new PlotRequest(
+ (window).submitterId+crypto.randomUUID(),
+ widget.config,
+ {
+ 'main': new RenderOptions(height,width, false, true),
+ 'fullScreen': new RenderOptions(fullHeight,fullWidth, false, true)
+ }
+ );
+ return request;
+ }
+
+
+ static height(size: PlotSize): number{
+ switch (size) {
+ case 'SMALL':
+ return 300;
+ case 'MEDIUM':
+ return 400;
+ case 'LARGE':
+ return 600;
+ }
+ }
+ static width(size: PlotSize): number{
+ switch (size) {
+ case 'SMALL':
+ return 400;
+ case 'MEDIUM':
+ return 600;
+ case 'LARGE':
+ return 900;
+ }
+ }
}
export type PlotSize = 'SMALL'|'MEDIUM'|'LARGE';
diff --git a/pdb-js/src/app/limit-by/limit-by.component.html b/pdb-js/src/app/limit-by/limit-by.component.html
index 5ba3622..2390897 100644
--- a/pdb-js/src/app/limit-by/limit-by.component.html
+++ b/pdb-js/src/app/limit-by/limit-by.component.html
@@ -17,6 +17,7 @@
+
) : boolean {
diff --git a/pdb-js/src/app/query-autocomplete/query-autocomplete.component.ts b/pdb-js/src/app/query-autocomplete/query-autocomplete.component.ts
index 69a8e4a..371161c 100644
--- a/pdb-js/src/app/query-autocomplete/query-autocomplete.component.ts
+++ b/pdb-js/src/app/query-autocomplete/query-autocomplete.component.ts
@@ -1,5 +1,5 @@
-import { Component, OnInit, Input, ViewChild } from '@angular/core';
-import {UntypedFormControl} from '@angular/forms';
+import { Component, OnInit, Input, ViewChild, AfterViewInit } from '@angular/core';
+import {FormControl, UntypedFormControl} from '@angular/forms';
import {Observable} from 'rxjs';
import {startWith, map} from 'rxjs/operators';
import {MatAutocompleteTrigger } from '@angular/material/autocomplete';
@@ -12,41 +12,48 @@ import { PlotService, PlotType, AutocompleteResult, Suggestion, ResultMode } fro
})
export class QueryAutocompleteComponent implements OnInit {
- queryField = new UntypedFormControl('');
+ queryField = new FormControl(new Suggestion("","",0));
suggestions = new UntypedFormControl();
filteredSuggestions!: Observable;
query : string = "";
+
+ suggestionFetcherEnabled = true;
@ViewChild(MatAutocompleteTrigger)
autocomplete!: MatAutocompleteTrigger;
- constructor(private plotService: PlotService) {}
+ constructor(private plotService: PlotService) {
+ }
ngOnInit() {
- const that = this;
this.query = "";
- this.queryField.valueChanges.subscribe(function(value){
- if (typeof value == "string") {
- that.query = value;
- }else{
- that.query = value.newQuery;
+ this.queryField.valueChanges.subscribe((value) =>{
+ if (value != null) {
+ if (typeof value == "string") {
+ this.query = value;
+ }else{
+ this.query = value.newQuery;
+
+ const el : HTMLInputElement = document.getElementById('query-autocomplete-input');
+ el.selectionStart=value.newCaretPosition;
+ el.selectionEnd=value.newCaretPosition;
+ }
- var el : HTMLInputElement = document.getElementById('query-autocomplete-input');
- el.selectionStart=value.newCaretPosition;
- el.selectionEnd=value.newCaretPosition;
- that.fetchSuggestions(value.newCaretPosition);
+ if (this.suggestionFetcherEnabled) {
+ this.fetchSuggestions(value.newCaretPosition);
+ }
}
});
this.filteredSuggestions = this.suggestions.valueChanges.pipe(
map(value => value)
);
}
-
+
onKey(event: any) {
//console.log(event);
if (event.key == "ArrowDown" || event.key == "ArrowUp"){
@@ -61,23 +68,21 @@ export class QueryAutocompleteComponent implements OnInit {
const that = this;
const query = typeof this.queryField.value == "string"
? this.queryField.value
- : this.queryField.value.newQuery;
+ : this.queryField.value!.newQuery;
this.plotService
.autocomplete(query, caretIndex, ResultMode.CUT_AT_DOT)
- .subscribe(
- (data: AutocompleteResult) => {// success path
- //console.log(JSON.stringify(data.proposals));
+ .subscribe({
+ next: (data: AutocompleteResult) => {
that.suggestions.setValue(data.proposals);
-
that.autocomplete.openPanel();
},
- (error:any) => console.log(error)
+ error: (error:any) => console.log(error)
+ }
);
}
displaySuggestion(suggestion?: Suggestion): string {
- //console.log("suggestion: "+JSON.stringify(suggestion));
return suggestion ? suggestion.newQuery : '';
}
}
diff --git a/pdb-js/src/app/visualization-page/visualization-page.component.html b/pdb-js/src/app/visualization-page/visualization-page.component.html
index 91c9c30..29735e4 100644
--- a/pdb-js/src/app/visualization-page/visualization-page.component.html
+++ b/pdb-js/src/app/visualization-page/visualization-page.component.html
@@ -52,7 +52,7 @@
- Gallery
+ Gallery
Split By:
diff --git a/pdb-js/src/app/visualization-page/visualization-page.component.scss b/pdb-js/src/app/visualization-page/visualization-page.component.scss
index 7bda29b..6d6b50a 100644
--- a/pdb-js/src/app/visualization-page/visualization-page.component.scss
+++ b/pdb-js/src/app/visualization-page/visualization-page.component.scss
@@ -15,11 +15,11 @@
grid:
"query-box query-box date-box" auto
"filters results results" 1fr
- / 25.5em 3fr 24em;
+ / 25.5em 3fr 23.5em;
}
}
-@media screen and (max-width: 1000px) {
+@media screen and (max-width: 900px) {
#visualization {
display: grid;
margin: 0;
@@ -27,7 +27,7 @@
grid:
"query-box" auto
"date-box" auto
- "filters" auto
+ "filters" min-content
"results" 1fr
/ 1fr;
}
diff --git a/pdb-js/src/app/visualization-page/visualization-page.component.ts b/pdb-js/src/app/visualization-page/visualization-page.component.ts
index b47b543..4e54369 100644
--- a/pdb-js/src/app/visualization-page/visualization-page.component.ts
+++ b/pdb-js/src/app/visualization-page/visualization-page.component.ts
@@ -1,13 +1,12 @@
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { PlotService, PlotType, PlotRequest, PlotResponse, TagField, FilterDefaults, DataType, YAxisDefinition, AxesTypes, PlotConfig, RenderOptions, RenderOptionsMap } from '../plot.service';
-import { UntypedFormControl, Validators } from '@angular/forms';
+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, SelectionRange, DateAnchor, LoadingEvent } from '../plot-view/plot-view.component';
+import { PlotViewComponent, LoadingEvent } from '../plot-view/plot-view.component';
import { GalleryViewComponent } from '../gallery-view/gallery-view.component';
-import * as moment from 'moment';
import { WidgetDimensions } from '../dashboard.service';
@Component({
@@ -15,14 +14,20 @@ import { WidgetDimensions } from '../dashboard.service';
templateUrl: './visualization-page.component.html',
styleUrls: ['./visualization-page.component.scss']
})
-export class VisualizationPageComponent implements OnInit {
+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: Array = [];
+ plotTypes: PlotType[] = [];
tagFields: Array = new Array();
@@ -68,33 +73,68 @@ export class VisualizationPageComponent implements OnInit {
}
ngOnInit() {
- const that = this;
(window).initDatePicker();
this.plotTypes = this.plotService.getPlotTypes();
this.selectedPlotType.push(this.plotTypes[0]);
- that.plotService.getFilterDefaults().subscribe(function(filterDefaults: FilterDefaults) {
+ this.plotService.getFilterDefaults().subscribe((filterDefaults: FilterDefaults) => {
- filterDefaults.fields.forEach(function(name:string) {
- that.tagFields.push(new TagField(name));
+ filterDefaults.fields.forEach((name:string) => {
+ this.tagFields.push(new TagField(name));
},
(error: any) => {
- that.showError(error.error.message);
+ this.showError(error.error.message);
});
- that.groupBy = that.tagFields.filter(val => filterDefaults.groupBy.includes(val.name));
- that.splitBy = that.tagFields.find(val => filterDefaults.splitBy == val.name);
- });
+ 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.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;
+ }
+ }
+}
+
loading(event: LoadingEvent) {
this.plotJobActive = event.loading;
}
- updateDateRange(newDateRange: string) {
+ updateDateRange(newDateRange: string, updatePlot=true) {
(document.getElementById("search-date-range")).value = newDateRange;
- this.plot();
+ if (updatePlot){
+ this.plot();
+ }
}
changePlotType(selectedPlotTypes: Array) {
diff --git a/pdb-js/src/index.html b/pdb-js/src/index.html
index cc3d665..0e83208 100644
--- a/pdb-js/src/index.html
+++ b/pdb-js/src/index.html
@@ -48,9 +48,6 @@
}
$( document ).ready(function() {
- //initDatePicker();
-
-
initInvaders('results');
document.addEventListener("invadersPause", function(event) {
pauseInvaders();