zoom by range selection
This commit is contained in:
5
pdb-js/package-lock.json
generated
5
pdb-js/package-lock.json
generated
@@ -7843,6 +7843,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.24.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
|
||||||
|
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
|
||||||
|
},
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"@angular/platform-browser": "^8.2.11",
|
"@angular/platform-browser": "^8.2.11",
|
||||||
"@angular/platform-browser-dynamic": "^8.2.11",
|
"@angular/platform-browser-dynamic": "^8.2.11",
|
||||||
"@angular/router": "^8.2.11",
|
"@angular/router": "^8.2.11",
|
||||||
|
"moment": "^2.24.0",
|
||||||
"rxjs": "~6.4.0",
|
"rxjs": "~6.4.0",
|
||||||
"rxjs-compat": "^6.5.3",
|
"rxjs-compat": "^6.5.3",
|
||||||
"tslib": "^1.10.0",
|
"tslib": "^1.10.0",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pdb-plot-view',
|
selector: 'pdb-plot-view',
|
||||||
@@ -18,6 +18,9 @@ export class PlotViewComponent implements OnInit {
|
|||||||
|
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
zoomRange : EventEmitter<SelectionRange> = new EventEmitter<SelectionRange>();
|
||||||
|
|
||||||
|
|
||||||
in_drag_mode = false;
|
in_drag_mode = false;
|
||||||
drag_start_x = 0;
|
drag_start_x = 0;
|
||||||
@@ -116,9 +119,27 @@ export class PlotViewComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dragStop(event) {
|
dragStop(event) {
|
||||||
//console.log("drag_stop");
|
if (this.in_drag_mode){
|
||||||
this.in_drag_mode = false;
|
this.in_drag_mode = false;
|
||||||
this.hideZoomInSlider();
|
this.hideZoomInSlider();
|
||||||
|
|
||||||
|
// Zoom in if the selected area has some arbitrary minimal size
|
||||||
|
if (Math.abs(this.drag_start_x - this.drag_end_x) > 10) {
|
||||||
|
|
||||||
|
const startPxInImage = Math.min(this.drag_start_x, this.drag_end_x);
|
||||||
|
const endPxInImage = Math.max(this.drag_start_x, this.drag_end_x);
|
||||||
|
|
||||||
|
const imageWidth = this.imageWidth();
|
||||||
|
const widthPlotArea = imageWidth - this.gnuplotLMargin - this.gnuplotRMargin;
|
||||||
|
const startPxWithinPlotArea = startPxInImage - this.gnuplotLMargin;
|
||||||
|
const endPxWithinPlotArea = endPxInImage - this.gnuplotLMargin;
|
||||||
|
|
||||||
|
const startPercentOfDateRange = startPxWithinPlotArea / widthPlotArea;
|
||||||
|
const endPercentOfDateRange = endPxWithinPlotArea / widthPlotArea;
|
||||||
|
|
||||||
|
this.zoomRange.emit(new SelectionRange(startPercentOfDateRange, endPercentOfDateRange));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dragAbort(event) {
|
dragAbort(event) {
|
||||||
@@ -131,3 +152,13 @@ export class PlotViewComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SelectionRange {
|
||||||
|
startPercentOfDateRange : number;
|
||||||
|
endPercentOfDateRange : number;
|
||||||
|
|
||||||
|
constructor(startPercentOfDateRange: number, endPercentOfDateRange: number){
|
||||||
|
this.startPercentOfDateRange = startPercentOfDateRange;
|
||||||
|
this.endPercentOfDateRange = endPercentOfDateRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="results">
|
<div id="results">
|
||||||
<pdb-plot-view #plotView></pdb-plot-view>
|
<pdb-plot-view #plotView (zoomRange)="zoomRange($event)"></pdb-plot-view>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ 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';
|
import { QueryAutocompleteComponent } from '../query-autocomplete/query-autocomplete.component';
|
||||||
import {PlotViewComponent } from '../plot-view/plot-view.component'
|
import {PlotViewComponent, SelectionRange } from '../plot-view/plot-view.component'
|
||||||
|
import * as moment from 'moment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pdb-visualization-page',
|
selector: 'pdb-visualization-page',
|
||||||
@@ -15,6 +15,8 @@ import {PlotViewComponent } from '../plot-view/plot-view.component'
|
|||||||
})
|
})
|
||||||
export class VisualizationPageComponent implements OnInit {
|
export class VisualizationPageComponent implements OnInit {
|
||||||
|
|
||||||
|
readonly DATE_PATTERN = "YYYY-MM-DD HH:mm:ss"; // for moment-JS
|
||||||
|
|
||||||
dateRange = new FormControl('2019-10-05 00:00:00 - 2019-10-11 23:59:59');
|
dateRange = new FormControl('2019-10-05 00:00:00 - 2019-10-11 23:59:59');
|
||||||
|
|
||||||
availablePlotTypes = {};
|
availablePlotTypes = {};
|
||||||
@@ -70,11 +72,7 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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 mainPlotType = selectedMainPlotType;
|
||||||
@@ -82,6 +80,10 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(mainPlotType));
|
const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(mainPlotType));
|
||||||
return compatiblePlotTypes;
|
return compatiblePlotTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dateRangeAsString() : string {
|
||||||
|
return (<HTMLInputElement>document.getElementById("search-date-range")).value;
|
||||||
|
}
|
||||||
|
|
||||||
plot(){
|
plot(){
|
||||||
const that = this;
|
const that = this;
|
||||||
@@ -90,20 +92,20 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
that.plotView.imageUrl = '';
|
that.plotView.imageUrl = '';
|
||||||
|
|
||||||
|
|
||||||
var aggregates = [];
|
const aggregates = [];
|
||||||
aggregates.push(this.selectedPlotType.value.id);
|
aggregates.push(this.selectedPlotType.value.id);
|
||||||
if (this.selectedCombinePlotType.value){
|
if (this.selectedCombinePlotType.value){
|
||||||
aggregates.push(this.selectedCombinePlotType.value.id);
|
aggregates.push(this.selectedCombinePlotType.value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = new PlotRequest();
|
const request = new PlotRequest();
|
||||||
request.query = this.query.query;
|
request.query = this.query.query;
|
||||||
request.height = document.getElementById("results").offsetHeight-1;
|
request.height = document.getElementById("results").offsetHeight-1;
|
||||||
request.width = document.getElementById("results").offsetWidth-1;
|
request.width = document.getElementById("results").offsetWidth-1;
|
||||||
request.groupBy = this.groupBy.map(o => o.name);
|
request.groupBy = this.groupBy.map(o => o.name);
|
||||||
request.limitBy = this.limitbycomponent.limitBy;
|
request.limitBy = this.limitbycomponent.limitBy;
|
||||||
request.limit = this.limitbycomponent.limit;
|
request.limit = this.limitbycomponent.limit;
|
||||||
request.dateRange = (<HTMLInputElement>document.getElementById("search-date-range")).value;
|
request.dateRange = this.dateRangeAsString();
|
||||||
request.yAxisScale = this.yAxisScale;
|
request.yAxisScale = this.yAxisScale;
|
||||||
request.aggregates = aggregates;
|
request.aggregates = aggregates;
|
||||||
request.keyOutside = false;
|
request.keyOutside = false;
|
||||||
@@ -120,9 +122,64 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
that.plotView.imageUrl = '';
|
that.plotView.imageUrl = '';
|
||||||
//that.plotView.errorMessage = JSON.stringify(error)
|
|
||||||
that.plotView.errorMessage = error.error.message;
|
that.plotView.errorMessage = error.error.message;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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});
|
||||||
|
|
||||||
|
console.log(newStartDate + " - " + newEndDate);
|
||||||
|
this.setDateRange(newStartDate, newEndDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseDateRange(dateRangeAsString : string) : DateRange {
|
||||||
|
if (dateRangeAsString) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DateRange {
|
||||||
|
startDate: any;
|
||||||
|
endDate: any;
|
||||||
|
duration: any;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,11 +42,6 @@
|
|||||||
'Last Year': [moment().subtract(1, 'year').startOf('year'),moment().subtract(1, 'year').endOf('year')],
|
'Last Year': [moment().subtract(1, 'year').startOf('year'),moment().subtract(1, 'year').endOf('year')],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#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>
|
||||||
|
|||||||
Reference in New Issue
Block a user