dashboard #1

Merged
andi merged 118 commits from dashboard into master 2024-09-29 06:47:35 +00:00
3 changed files with 160 additions and 124 deletions
Showing only changes of commit d52033b5f0 - Show all commits

View File

@@ -1,5 +1,7 @@
import { Component, OnInit, Output, EventEmitter } from '@angular/core'; import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { DataType, AxesTypes, PlotResponseStats } from '../plot.service'; import { DataType, AxesTypes, PlotResponseStats, PlotConfig, PlotService, PlotResponse, PlotRequest } from '../plot.service';
import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar';
import * as moment from 'moment';
@Component({ @Component({
selector: 'pdb-plot-view', selector: 'pdb-plot-view',
@@ -8,6 +10,7 @@ import { DataType, AxesTypes, PlotResponseStats } from '../plot.service';
}) })
export class PlotViewComponent implements OnInit { export class PlotViewComponent implements OnInit {
readonly DATE_PATTERN = "YYYY-MM-DD HH:mm:ss"; // for moment-JS
readonly gnuplotLMargin = 110; // The left margin configured for gnuplot readonly gnuplotLMargin = 110; // The left margin configured for gnuplot
readonly gnuplotRMargin = 110; // The right margin configured for gnuplot readonly gnuplotRMargin = 110; // The right margin configured for gnuplot
@@ -19,12 +22,12 @@ export class PlotViewComponent implements OnInit {
stats: PlotResponseStats | null = null; stats: PlotResponseStats | null = null;
axes!: AxesTypes; axes!: AxesTypes;
@Output() @Output()
zoomRange : EventEmitter<SelectionRange> = new EventEmitter<SelectionRange>(); loadingEvent : EventEmitter<LoadingEvent> = new EventEmitter<LoadingEvent>();
@Output() @Output()
zoomWithDateAnchor : EventEmitter<DateAnchor> = new EventEmitter<DateAnchor>(); dateRangeUpdateEvent : EventEmitter<string> = new EventEmitter<string>();
in_drag_mode = false; in_drag_mode = false;
drag_start_x = 0; drag_start_x = 0;
@@ -41,10 +44,22 @@ export class PlotViewComponent implements OnInit {
showStats = false; showStats = false;
constructor() { } config? : PlotConfig;
submitterId = crypto.randomUUID();
constructor(private service : PlotService, private snackBar: MatSnackBar) { }
ngOnInit() { ngOnInit() {
} }
showError(message:string) {
this.snackBar.open(message, "", {
duration: 5000,
verticalPosition: 'top'
});
}
hideZoomInSlider() { hideZoomInSlider() {
this.zoomInSliderStyleDisplay = "none"; this.zoomInSliderStyleDisplay = "none";
@@ -147,7 +162,7 @@ export class PlotViewComponent implements OnInit {
const startPercentOfDateRange = startPxWithinPlotArea / widthPlotArea; const startPercentOfDateRange = startPxWithinPlotArea / widthPlotArea;
const endPercentOfDateRange = endPxWithinPlotArea / widthPlotArea; const endPercentOfDateRange = endPxWithinPlotArea / widthPlotArea;
this.zoomRange.emit(new SelectionRange(startPercentOfDateRange, endPercentOfDateRange)); this.zoomRange(new SelectionRange(startPercentOfDateRange, endPercentOfDateRange));
} }
} }
} }
@@ -161,6 +176,25 @@ export class PlotViewComponent implements OnInit {
this.hideZoomInSlider(); this.hideZoomInSlider();
} }
} }
setDateRange(startDate: any, endDate: any) {
const formattedStartDate = startDate.format(this.DATE_PATTERN);
const formattedEndDate = endDate.format(this.DATE_PATTERN);
const newDateRange = formattedStartDate+" - "+formattedEndDate;
//(<HTMLInputElement>document.getElementById("search-date-range")).value = newDateRange;
this.dateRangeUpdateEvent.emit(newDateRange);
//this.plot();
}
zoomRange(range: SelectionRange) {
this.shiftDate(this.config?.dateRange!, range.startPercentOfDateRange, range.endPercentOfDateRange-1);
}
zoomWithDateAnchor(dateAnchor: DateAnchor){
this.shiftDateByAnchor(this.config?.dateRange!, dateAnchor.cursorPercentOfDateRange, dateAnchor.zoomFactor);
}
zoomByScroll(event: WheelEvent) { zoomByScroll(event: WheelEvent) {
if (this.isInImage(event) && event.deltaY != 0 && this.axes.hasXAxis(DataType.Time)) { if (this.isInImage(event) && event.deltaY != 0 && this.axes.hasXAxis(DataType.Time)) {
@@ -175,7 +209,7 @@ export class PlotViewComponent implements OnInit {
const zoomFactor = event.deltaY < 0 ? 0.5 : 2; const zoomFactor = event.deltaY < 0 ? 0.5 : 2;
this.zoomWithDateAnchor.emit(new DateAnchor(cursorPercentOfDateRange, zoomFactor)); this.zoomWithDateAnchor(new DateAnchor(cursorPercentOfDateRange, zoomFactor));
} }
} }
@@ -186,6 +220,100 @@ export class PlotViewComponent implements OnInit {
hideDetails() { hideDetails() {
this.showStats = false; this.showStats = false;
} }
plot(config : PlotConfig, axes: AxesTypes){
this.config = config;
this.axes = axes;
const request = this.createPlotRequest();
this.loadingEvent.emit(new LoadingEvent(true));
const x = this.service.sendPlotRequest(request).subscribe({
next: (plotResponse: PlotResponse) => {
this.imageUrl = "http://"+window.location.hostname+':'+window.location.port+'/'+plotResponse.imageUrl;
this.stats = plotResponse.stats;
document.dispatchEvent(new Event("invadersPause", {}));
this.loadingEvent.emit(new LoadingEvent(false));
},
error: (error:any) => {
this.imageUrl = '';
this.stats = null;
this.showError(error.error.message);
document.dispatchEvent(new Event("invadersPause", {}));
this.loadingEvent.emit(new LoadingEvent(false));
}
});
}
createPlotRequest(): PlotRequest {
const results = document.getElementById("results");
const request = new PlotRequest(
results != null ? results.offsetHeight-1: 1024,
results != null ? results.offsetWidth-1 : 1024,
300, // thumbnailMaxWidth
200, // thumbnailMaxHeight
false, // keyOutside
false, // generateThumbnail
this.submitterId,
this.config!);
return request;
}
/**
* Zoom in/out by zoomFaktor, so that the anchorInPercentOfDateRange keeps the same position.
*
* shiftDateByAnchor(dateRangeAsString, 0.20, 0.5) zooms in by 50%, so that the date that was at 20% before the zoom is still at 20% after the zoom
* shiftDateByAnchor(dateRangeAsString, 0.33, 2) zooms out by 50%, so that the date that was at 33% before the zoom is still at 33% after the zoom
*/
shiftDateByAnchor(dateRange:string, anchorInPercentOfDateRange:number, zoomFactor:number)
{
const dateRangeParsed = this.parseDateRange(dateRange);
const dateRangeInSeconds = dateRangeParsed.duration.asSeconds();
const anchorTimestampInSeconds = dateRangeParsed.startDate.clone().add(Math.floor(dateRangeInSeconds*anchorInPercentOfDateRange), "seconds");
const newDateRangeInSeconds = dateRangeInSeconds * zoomFactor;
const newStartDate = anchorTimestampInSeconds.clone().subtract(newDateRangeInSeconds*anchorInPercentOfDateRange, "seconds");
const newEndDate = newStartDate.clone().add({seconds: newDateRangeInSeconds});;
this.setDateRange(newStartDate, newEndDate);
}
/**
* Zoom in/out or shift date by adding factorStartDate*dateRangeInSeconds seconds to the start date
* and factorEndDate*dateRangeInSeconds seconds to the end date.
*
* shiftDate(dateRangeAsString, 0.25, -0.25) will zoom in, making the range half its size
* shiftDate(dateRangeAsString, -0.5, 0.5) will zoom out, making the range double its size
* shiftDate(dateRangeAsString, -0.5, -0.5) will move the range by half its size to older values
* shiftDate(dateRangeAsString, 1, 1) will move the range by its size to newer values
*/
shiftDate(dateRange: string, factorStartDate: number, factorEndDate: number)
{
const dateRangeParsed = this.parseDateRange(dateRange);
const dateRangeInSeconds = dateRangeParsed.duration.asSeconds();
const newStartDate = dateRangeParsed.startDate.add({seconds: dateRangeInSeconds*factorStartDate});
const newEndDate = dateRangeParsed.endDate.add({seconds: dateRangeInSeconds*factorEndDate});
this.setDateRange(newStartDate, newEndDate);
}
parseDateRange(dateRangeAsString : string) : DateRange {
const startDate = moment(dateRangeAsString.slice(0, 19));
const endDate = moment(dateRangeAsString.slice(22, 41));
return {
startDate: startDate,
endDate: endDate,
duration: moment.duration(endDate.diff(startDate))
};
}
} }
export class SelectionRange { export class SelectionRange {
@@ -206,4 +334,14 @@ export class DateAnchor {
this.cursorPercentOfDateRange = cursorPercentOfDateRange; this.cursorPercentOfDateRange = cursorPercentOfDateRange;
this.zoomFactor = zoomFactor; this.zoomFactor = zoomFactor;
} }
}
export class LoadingEvent {
constructor(public loading: boolean){}
}
export class DateRange {
startDate: any;
endDate: any;
duration: any;
} }

View File

@@ -96,8 +96,8 @@
<div id="results"> <div id="results">
<pdb-plot-view <pdb-plot-view
#plotView #plotView
(zoomRange)="zoomRange($event)" (loadingEvent)="loading($event)"
(zoomWithDateAnchor)="zoomWithDateAnchor($event)"></pdb-plot-view> (dateRangeUpdateEvent)="updateDateRange($event)"></pdb-plot-view>
<pdb-gallery-view <pdb-gallery-view
#galleryView> #galleryView>
</pdb-gallery-view> </pdb-gallery-view>

View File

@@ -5,7 +5,7 @@ import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack
import { LimitByComponent } from '../limit-by/limit-by.component'; import { LimitByComponent } from '../limit-by/limit-by.component';
import { YAxisDefinitionComponent } from '../y-axis-definition/y-axis-definition.component'; import { YAxisDefinitionComponent } from '../y-axis-definition/y-axis-definition.component';
import { QueryAutocompleteComponent } from '../query-autocomplete/query-autocomplete.component'; import { QueryAutocompleteComponent } from '../query-autocomplete/query-autocomplete.component';
import { PlotViewComponent, SelectionRange, DateAnchor } from '../plot-view/plot-view.component'; import { PlotViewComponent, SelectionRange, DateAnchor, LoadingEvent } from '../plot-view/plot-view.component';
import { GalleryViewComponent } from '../gallery-view/gallery-view.component'; import { GalleryViewComponent } from '../gallery-view/gallery-view.component';
import * as moment from 'moment'; import * as moment from 'moment';
@@ -89,6 +89,14 @@ export class VisualizationPageComponent implements OnInit {
that.splitBy = that.tagFields.find(val => filterDefaults.splitBy == val.name); that.splitBy = that.tagFields.find(val => filterDefaults.splitBy == val.name);
}); });
} }
loading(event: LoadingEvent) {
this.plotJobActive = event.loading;
}
updateDateRange(newDateRange: string) {
(<HTMLInputElement>document.getElementById("search-date-range")).value = newDateRange;
this.plot();
}
changePlotType(selectedPlotTypes: Array<PlotType>) { changePlotType(selectedPlotTypes: Array<PlotType>) {
const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(selectedPlotTypes)); const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(selectedPlotTypes));
@@ -151,34 +159,9 @@ export class VisualizationPageComponent implements OnInit {
} }
plot(){ plot(){
const that = this; const config = this.createPlotConfig();
const axes = this.getAxes();
that.plotView.imageUrl = ''; this.plotView.plot(config, axes);
that.plotView.stats = null;
this.plotJobActive = true;
this.plotView.axes = this.getAxes();
console.log(JSON.stringify(this.getAxes()));
that.galleryView.show=false;
document.dispatchEvent(new Event("invadersStart", {}));
const request = this.createPlotRequest();
this.plotService.sendPlotRequest(request).subscribe({
next: (plotResponse: PlotResponse) => {
this.plotView.imageUrl = "http://"+window.location.hostname+':'+window.location.port+'/'+plotResponse.imageUrl;
this.plotView.stats = plotResponse.stats;
this.plotJobActive = false;
document.dispatchEvent(new Event("invadersPause", {}));
},
error: (error:any) => {
console.log(JSON.stringify(error));
this.plotView.imageUrl = '';
this.plotView.stats = null;
this.plotJobActive = false;
this.showError(error.error.message);
document.dispatchEvent(new Event("invadersPause", {}));
}
});
} }
createPlotConfig(): PlotConfig { createPlotConfig(): PlotConfig {
@@ -220,89 +203,4 @@ export class VisualizationPageComponent implements OnInit {
config); config);
return request; return request;
} }
/**
* Zoom in/out by zoomFaktor, so that the anchorInPercentOfDateRange keeps the same position.
*
* shiftDateByAnchor(dateRangeAsString, 0.20, 0.5) zooms in by 50%, so that the date that was at 20% before the zoom is still at 20% after the zoom
* shiftDateByAnchor(dateRangeAsString, 0.33, 2) zooms out by 50%, so that the date that was at 33% before the zoom is still at 33% after the zoom
*/
shiftDateByAnchor(dateRange:string, anchorInPercentOfDateRange:number, zoomFactor:number)
{
const dateRangeParsed = this.parseDateRange(dateRange);
const dateRangeInSeconds = dateRangeParsed.duration.asSeconds();
const anchorTimestampInSeconds = dateRangeParsed.startDate.clone().add(Math.floor(dateRangeInSeconds*anchorInPercentOfDateRange), "seconds");
const newDateRangeInSeconds = dateRangeInSeconds * zoomFactor;
const newStartDate = anchorTimestampInSeconds.clone().subtract(newDateRangeInSeconds*anchorInPercentOfDateRange, "seconds");
const newEndDate = newStartDate.clone().add({seconds: newDateRangeInSeconds});;
this.setDateRange(newStartDate, newEndDate);
}
/**
* Zoom in/out or shift date by adding factorStartDate*dateRangeInSeconds seconds to the start date
* and factorEndDate*dateRangeInSeconds seconds to the end date.
*
* shiftDate(dateRangeAsString, 0.25, -0.25) will zoom in, making the range half its size
* shiftDate(dateRangeAsString, -0.5, 0.5) will zoom out, making the range double its size
* shiftDate(dateRangeAsString, -0.5, -0.5) will move the range by half its size to older values
* shiftDate(dateRangeAsString, 1, 1) will move the range by its size to newer values
*/
shiftDate(dateRange: string, factorStartDate: number, factorEndDate: number)
{
const dateRangeParsed = this.parseDateRange(dateRange);
const dateRangeInSeconds = dateRangeParsed.duration.asSeconds();
const newStartDate = dateRangeParsed.startDate.add({seconds: dateRangeInSeconds*factorStartDate});
const newEndDate = dateRangeParsed.endDate.add({seconds: dateRangeInSeconds*factorEndDate});
this.setDateRange(newStartDate, newEndDate);
}
parseDateRange(dateRangeAsString : string) : DateRange {
const startDate = moment(dateRangeAsString.slice(0, 19));
const endDate = moment(dateRangeAsString.slice(22, 41));
return {
startDate: startDate,
endDate: endDate,
duration: moment.duration(endDate.diff(startDate))
};
}
setDateRange(startDate: any, endDate: any) {
const formattedStartDate = startDate.format(this.DATE_PATTERN);
const formattedEndDate = endDate.format(this.DATE_PATTERN);
const newDateRange = formattedStartDate+" - "+formattedEndDate;
(<HTMLInputElement>document.getElementById("search-date-range")).value = newDateRange;
this.plot();
}
zoomRange(range: SelectionRange) {
this.shiftDate(this.dateRangeAsString(), range.startPercentOfDateRange, range.endPercentOfDateRange-1);
}
zoomWithDateAnchor(dateAnchor: DateAnchor){
this.shiftDateByAnchor(this.dateRangeAsString(), dateAnchor.cursorPercentOfDateRange, dateAnchor.zoomFactor);
}
} }
export class DateRange {
startDate: any;
endDate: any;
duration: any;
}
/*
export class AxesUsed {
x1: DataType;
y1: DataType;
x2: DataType;
y2: DataType;
}
*/