From 38c54200d67c04bdac8d136d3b5a83d819d7498a Mon Sep 17 00:00:00 2001 From: Daniel Steger Date: Fri, 5 Jun 2020 16:32:28 +0200 Subject: [PATCH 1/4] Added url handling for new distribution chart. --- .../aggregation-chart.component.ts | 22 ++++---- .../aggregation-chart-data.service.ts | 54 ++++++++++--------- .../violin-chart/violin-chart.component.html | 2 +- .../violin-chart/violin-chart.component.ts | 41 +++++++++++++- .../distribution/distribution.component.ts | 23 ++++++-- .../services/result-selection.store.ts | 46 +++++++++++++--- .../distributionChartUrlHandling.js | 2 +- .../osm/result/AggregationController.groovy | 2 +- 8 files changed, 139 insertions(+), 53 deletions(-) diff --git a/frontend/src/app/modules/aggregation/components/aggregation-chart/aggregation-chart.component.ts b/frontend/src/app/modules/aggregation/components/aggregation-chart/aggregation-chart.component.ts index 92df6742b1..2ea88a2125 100644 --- a/frontend/src/app/modules/aggregation/components/aggregation-chart/aggregation-chart.component.ts +++ b/frontend/src/app/modules/aggregation/components/aggregation-chart/aggregation-chart.component.ts @@ -17,9 +17,10 @@ import {AggregationChartDataByMeasurand} from '../../models/aggregation-chart-da export class AggregationChartComponent implements OnChanges { @ViewChild('svg') svgElement: ElementRef; - @Input() barchartAverageData = []; - @Input() barchartMedianData = []; + @Input() barchartAverageData = {}; + @Input() barchartMedianData = {}; + filterRules = {}; hasFilterRules = false; showDiagramTypeSwitch = false; @@ -40,7 +41,6 @@ export class AggregationChartComponent implements OnChanges { private dataForScoreBar: { min: number, max: number, barsToRender: Array }; private measurandDataMap: AggregationChartDataByMeasurand = {}; - private filterRules = {}; private dataForHeader = ''; private sideLabels: string[] = []; private anyHighlighted = false; @@ -59,28 +59,28 @@ export class AggregationChartComponent implements OnChanges { selectDiagramType(diagramType: string) { this.aggregationChartDataService.stackBars = (diagramType === 'stacked'); - this.aggregationChartDataService.writeAdditionalQueryParams(); + this.aggregationChartDataService.writeQueryWithAdditionalParams(); this.redraw(); } selectAggregationType(aggregationType: string): void { this.aggregationChartDataService.aggregationType = aggregationType; - this.aggregationChartDataService.writeAdditionalQueryParams(); + this.aggregationChartDataService.writeQueryWithAdditionalParams(); this.redraw(); } selectFilter(filter: string): void { - this.aggregationChartDataService.selectedFilter = filter; - this.aggregationChartDataService.writeAdditionalQueryParams(); + this.aggregationChartDataService.filter = filter; + this.aggregationChartDataService.writeQueryWithAdditionalParams(); this.redraw(); } redraw(): void { - if (Object.keys(this.barchartAverageData).length < 1) { + if (Object.keys(this.barchartAverageData).length < 1 || Object.keys(this.barchartMedianData).length < 1) { return; - } else if (Object.keys(this.barchartMedianData).length === 0) { + } else if (this.barchartMedianData.hasOwnProperty('series') && this.barchartMedianData['series'].length === 0) { this.aggregationChartDataService.aggregationType = 'avg'; - this.aggregationChartDataService.writeAdditionalQueryParams(); + this.aggregationChartDataService.writeQueryWithAdditionalParams(); } this.aggregationChartDataService.setData(); @@ -140,7 +140,7 @@ export class AggregationChartComponent implements OnChanges { } enoughPercentileValues(): boolean { - return Object.keys(this.barchartMedianData).length >= 1; + return this.barchartMedianData.hasOwnProperty('series') && this.barchartMedianData['series'].length > 0; } private render(): void { diff --git a/frontend/src/app/modules/aggregation/services/aggregation-chart-data.service.ts b/frontend/src/app/modules/aggregation/services/aggregation-chart-data.service.ts index 5562ad38d7..f16e98c85a 100644 --- a/frontend/src/app/modules/aggregation/services/aggregation-chart-data.service.ts +++ b/frontend/src/app/modules/aggregation/services/aggregation-chart-data.service.ts @@ -22,7 +22,7 @@ export class AggregationChartDataService { filterRules = {}; i18nMap: { comparativeDeterioration: string, comparativeImprovement: string, jobGroup: string, measurand: string, page: string }; series: AggregationChartSeries[] = []; - selectedFilter = 'asc'; + filter = 'asc'; aggregationType = 'avg'; percentileValue = 50; stackBars = false; @@ -67,12 +67,7 @@ export class AggregationChartDataService { private translateService: TranslateService, private measurandColorService: MeasurandColorService ) { - route.queryParams.subscribe((params: Params) => { - this.selectedFilter = params.selectedFilter ? params.selectedFilter : this.selectedFilter; - this.aggregationType = params.selectedAggregationValue ? params.selectedAggregationValue : this.aggregationType; - this.stackBars = params.stackBars === '1'; - this.percentileValue = params.selectedPercentile ? parseInt(params.selectedPercentile, 10) : this.percentileValue; - }); + this.readChartSettingsByUrl(); } getBarchartData(resultSelectionCommand: ResultSelectionCommand, @@ -86,7 +81,7 @@ export class AggregationChartDataService { this.hideChartIfNoDataAvailable(); }); - this.writeAdditionalQueryParams(); + this.writeQueryWithAdditionalParams(); this.barchartDataService.fetchBarchartData( resultSelectionCommand, @@ -121,11 +116,11 @@ export class AggregationChartDataService { URL.AGGREGATION_BARCHART_DATA ).subscribe(result => { this.barchartMedianData$.next(this.sortDataByMeasurandOrder(result)); - this.writeAdditionalQueryParams(); + this.writeQueryWithAdditionalParams(); }); } - public setData(): void { + setData(): void { let data; if (this.aggregationType === 'percentile') { data = this.barchartMedianData$.getValue(); @@ -148,7 +143,7 @@ export class AggregationChartDataService { } } - public setMeasurandDataMap(series: AggregationChartSeries[]): void { + setMeasurandDataMap(series: AggregationChartSeries[]): void { let measurands: string[] = []; const measurandDataMap: AggregationChartDataByMeasurand = {}; if (series) { @@ -202,7 +197,7 @@ export class AggregationChartDataService { this.allMeasurandDataMap = measurandDataMap; } - public setDataForScoreBar(): void { + setDataForScoreBar(): void { const barsToRender = []; let minValue = 0; let maxValue = 0; @@ -259,7 +254,7 @@ export class AggregationChartDataService { } } - public setDataForHeader(): void { + setDataForHeader(): void { const data = this.getDataForLabels(); let header = ''; let aggregation = ''; @@ -281,11 +276,11 @@ export class AggregationChartDataService { this.dataForHeader = header; } - public setUniqueSideLabels(): void { + setUniqueSideLabels(): void { this.uniqueSideLabels = this.getDataForLabels().map(x => x.sideLabel).filter((el, i, a) => i === a.indexOf(el)); } - public createEmptyBarsForMissingData(): void { + createEmptyBarsForMissingData(): void { let sideLabelsForMeasurand: string[] = []; Object.keys(this.allMeasurandDataMap).forEach((measurand) => { const data = this.allMeasurandDataMap[measurand]; @@ -312,7 +307,7 @@ export class AggregationChartDataService { }); } - public setComparativeData(series: AggregationChartSeries[]) { + setComparativeData(series: AggregationChartSeries[]) { const comparativeData: AggregationChartSeries[] = []; series.forEach(datum => { const difference = datum.value - datum.valueComparative; @@ -341,17 +336,26 @@ export class AggregationChartDataService { return series.concat(comparativeData); } - writeAdditionalQueryParams(): void { + writeQueryWithAdditionalParams(): void { const additionalParams: Params = { - selectedFilter: this.selectedFilter, - selectedAggregationValue: this.aggregationType, - selectedPercentile: this.percentileValue, + filter: this.filter, + aggregationType: this.aggregationType, + percentileValue: this.percentileValue, stackBars: this.stackBars ? 1 : 0 }; this.resultSelectionStore.writeQueryParams(additionalParams); } + private readChartSettingsByUrl(): void { + this.route.queryParams.subscribe((params: Params) => { + this.filter = params.filter ? params.filter : this.filter; + this.aggregationType = params.aggregationType ? params.aggregationType : this.aggregationType; + this.stackBars = params.stackBars === '1'; + this.percentileValue = params.percentileValue ? parseInt(params.percentileValue, 10) : this.percentileValue; + }); + } + private sortDataByMeasurandOrder(data) { if (Object.getOwnPropertyNames(data).length < 1) { return data; @@ -368,22 +372,22 @@ export class AggregationChartDataService { } private sortSeriesByFilterRule(data): void { - if (this.selectedFilter === 'desc') { + if (this.filter === 'desc') { this.ascSelected = false; this.descSelected = true; Object.keys(this.filterRules).forEach((key) => this.filterRules[key].selected = false); data.series = data.series.sort((a, b) => (a.value > b.value) ? -1 : ((b.value > a.value) ? 1 : 0)); - } else if (Object.keys(this.filterRules).includes(this.selectedFilter)) { + } else if (Object.keys(this.filterRules).includes(this.filter)) { this.ascSelected = false; this.descSelected = false; Object .keys(this.filterRules) - .forEach((key) => key === this.selectedFilter ? this.filterRules[key].selected = true : this.filterRules[key].selected = false); - const keyForFilterRule = Object.keys(this.filterRules).filter((key) => key === this.selectedFilter).toString(); + .forEach((key) => key === this.filter ? this.filterRules[key].selected = true : this.filterRules[key].selected = false); + const keyForFilterRule = Object.keys(this.filterRules).filter((key) => key === this.filter).toString(); const filterRule = this.filterRules[keyForFilterRule]; data.series = data.series.filter(datum => filterRule.some(x => datum.jobGroup === x.jobGroup && datum.page === x.page)); } else { - this.selectedFilter = 'asc'; + this.filter = 'asc'; this.ascSelected = true; this.descSelected = false; Object.keys(this.filterRules).forEach((key) => this.filterRules[key].selected = false); diff --git a/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.html b/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.html index 5e985d9d81..7356767ca9 100644 --- a/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.html +++ b/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.html @@ -3,7 +3,7 @@
- 0; } + private readChartSettingsByUrl(): void { + this.route.queryParams.subscribe((params: Params) => { + this.selectedSortingRule = params.sortingRule ? params.sortingRule : ''; + this.selectedFilterRule = params.filterRule ? params.filterRule : ''; + this.dataTrimValue = params.maxValue ? params.maxValue : this.dataTrimValue; + + if (this.selectedSortingRule === '' && this.selectedFilterRule === '') { + this.selectedSortingRule = 'desc'; + } else if (this.selectedSortingRule !== '' && this.selectedFilterRule !== '') { + this.selectedSortingRule = ''; + } + }); + } + private prepareChartData(inputData: DistributionDataDTO): DistributionDataDTO { const chartData = {...inputData}; chartData.series.forEach((elem: DistributionDTO) => { @@ -136,7 +173,7 @@ export class ViolinChartComponent implements OnChanges { } private sortSeries(): DistributionDTO[] { - if ((this.selectedSortingRule === 'desc' || this.selectedSortingRule === 'asc') && this.selectedFilterRule.length === 0) { + if ((this.selectedSortingRule === 'desc' || this.selectedSortingRule === 'asc') && this.selectedFilterRule === '') { return this.chartData.sortingRules[this.selectedSortingRule].map(trace => { return this.chartData.series[trace]; }); diff --git a/frontend/src/app/modules/distribution/distribution.component.ts b/frontend/src/app/modules/distribution/distribution.component.ts index 1a221c6536..22f4e50b42 100644 --- a/frontend/src/app/modules/distribution/distribution.component.ts +++ b/frontend/src/app/modules/distribution/distribution.component.ts @@ -1,32 +1,45 @@ -import { Component } from '@angular/core'; -import {DistributionDataDTO, DistributionData} from './models/distribution-data.model'; +import {Component, OnInit, ViewChild} from '@angular/core'; +import {DistributionData, DistributionDataDTO} from './models/distribution-data.model'; import {URL} from '../../enums/url.enum'; import {ResultSelectionStore} from '../result-selection/services/result-selection.store'; import {BehaviorSubject} from 'rxjs'; import {ViolinchartDataService} from './services/violinchart-data.service'; +import {ViolinChartComponent} from './components/violin-chart/violin-chart.component'; @Component({ selector: 'osm-distribution', templateUrl: './distribution.component.html', styleUrls: ['./distribution.component.scss'] }) -export class DistributionComponent { +export class DistributionComponent implements OnInit { showChartCard = false; results$ = new BehaviorSubject(new DistributionData()); + @ViewChild(ViolinChartComponent) + private violinChartComponent: ViolinChartComponent; + constructor(private violinChartService: ViolinchartDataService, private resultSelectionStore: ResultSelectionStore) { } - getDistributionChartData() { + ngOnInit() { + this.showChartCard = false; + if (this.resultSelectionStore.validQuery) { + this.getDistributionChartData(); + } + } + + getDistributionChartData(): void { this.results$.next(null); this.showChartCard = true; + this.violinChartComponent.writeQueryWithAdditionalParams(); + this.violinChartService.fetchDistributionData( this.resultSelectionStore.resultSelectionCommand, this.resultSelectionStore.remainingResultSelection, URL.DISTRIBUTION_VIOLINCHART_DATA - ).subscribe(next => { + ).subscribe((next: DistributionDataDTO) => { this.results$.next(next); }); } diff --git a/frontend/src/app/modules/result-selection/services/result-selection.store.ts b/frontend/src/app/modules/result-selection/services/result-selection.store.ts index e373127d57..7d63285587 100644 --- a/frontend/src/app/modules/result-selection/services/result-selection.store.ts +++ b/frontend/src/app/modules/result-selection/services/result-selection.store.ts @@ -55,15 +55,32 @@ export class ResultSelectionStore { validQuery = false; - oldToNewChartKeyMap = { + oldToNewChartKeyMap: {[key: string]: string} = { + // General selectedFolder: 'jobGroupIds', selectedPages: 'pageIds', selectedAggrGroupValuesUnCached: 'measurands', selectedBrowsers: 'browserIds', selectedLocations: 'locationIds', + + // Time series comparativeFrom: 'fromComparative', comparativeTo: 'toComparative', - selectedTimeFrameInterval: 'interval' + selectedTimeFrameInterval: 'interval', + trimAboveLoadTimes: 'maxLoadTimes', + trimAboveRequestCounts: 'maxRequestCounts', + trimAboveRequestSizes: 'maxRequestSizes', + trimBelowLoadTimes: 'minLoadTimes', + trimBelowRequestCounts: 'minRequestCounts', + trimBelowRequestSizes: 'minRequestSizes', + + // Aggregation + selectedAggregationValue: 'aggregationType', + selectedFilter: 'filter', + selectedPercentile: 'precentileValue', + + // Distribution + measurand: 'measurands' }; constructor(private resultSelectionService: ResultSelectionService, private route: ActivatedRoute, private router: Router) { @@ -225,14 +242,29 @@ export class ResultSelectionStore { return date instanceof Date && !isNaN(date.getTime()); } - private renameParamKeys = (keysMap, object) => - Object.keys(object).reduce( - (acc, key) => ({ + private renameParamKeys(keysMap: {[k: string]: string}, params: Params): Params { + return Object.keys(params).reduce( + (acc: {}, key: string) => ({ ...acc, - ...{[keysMap[key] || key]: object[key]} + ...{[keysMap[key] || key]: this.getParamValue(key, params)} }), {} - ) + ); + } + + private getParamValue(key: string, params: Params): string { + if (key === 'measurand') { + try { + const json = JSON.parse(decodeURIComponent(params[key])); + if (json && typeof json === 'object' && json.hasOwnProperty('values')) { + return json.values; + } + } catch { + return params[key]; + } + } + return params[key]; + } private setRemainingResultSelection(newState: RemainingResultSelection): void { this.dataAvailable$.next(true); diff --git a/grails-app/assets/javascripts/distributionChart/distributionChartUrlHandling.js b/grails-app/assets/javascripts/distributionChart/distributionChartUrlHandling.js index e06059e505..9bbcda003c 100644 --- a/grails-app/assets/javascripts/distributionChart/distributionChartUrlHandling.js +++ b/grails-app/assets/javascripts/distributionChart/distributionChartUrlHandling.js @@ -35,7 +35,7 @@ OpenSpeedMonitor.ChartModules.UrlHandling.DistributionChart = (function () { }); measurands.push(json); }); - map['measurand'] = measurands + map['measurand'] = encodeURIComponent(measurands); }; var addHandler = function () { $('#graphButtonHtmlId').on('click', updateUrl); diff --git a/grails-app/controllers/de/iteratec/osm/result/AggregationController.groovy b/grails-app/controllers/de/iteratec/osm/result/AggregationController.groovy index dfd25d37ae..64df66c084 100644 --- a/grails-app/controllers/de/iteratec/osm/result/AggregationController.groovy +++ b/grails-app/controllers/de/iteratec/osm/result/AggregationController.groovy @@ -54,7 +54,7 @@ class AggregationController extends ExceptionHandlerController { // return if no data is available boolean hasComparativeData = barchartAggregations.any { it.valueComparative != null } if (!barchartAggregations.any { it.value != null } && !hasComparativeData) { - ControllerUtils.sendObjectAsJSON(response, [:]) + ControllerUtils.sendObjectAsJSON(response, new AggregationChartDTO(series: [])) return } From e61b51fe469bb5673bfa5c952d91ca94bc9e47bf Mon Sep 17 00:00:00 2001 From: Daniel Steger Date: Mon, 8 Jun 2020 09:52:17 +0200 Subject: [PATCH 2/4] Fixed angular tests --- .../violin-chart/violin-chart.component.spec.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.spec.ts b/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.spec.ts index 71454eda42..af4409c3c0 100644 --- a/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.spec.ts +++ b/frontend/src/app/modules/distribution/components/violin-chart/violin-chart.component.spec.ts @@ -3,6 +3,8 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ViolinChartComponent} from './violin-chart.component'; import {SharedModule} from '../../../shared/shared.module'; import {SharedMocksModule} from '../../../../testing/shared-mocks.module'; +import {ResultSelectionStore} from '../../../result-selection/services/result-selection.store'; +import {ResultSelectionService} from '../../../result-selection/services/result-selection.service'; describe('ViolinChartComponent', () => { let component: ViolinChartComponent; @@ -11,7 +13,14 @@ describe('ViolinChartComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ViolinChartComponent], - imports: [SharedModule, SharedMocksModule] + imports: [ + SharedModule, + SharedMocksModule + ], + providers: [ + ResultSelectionStore, + ResultSelectionService + ] }) .compileComponents(); })); From 0046b4484b5d51eb1b0ffe6ebbf6816ed9c5a6eb Mon Sep 17 00:00:00 2001 From: Daniel Steger Date: Wed, 24 Jun 2020 12:38:30 +0200 Subject: [PATCH 3/4] URL handling for time series chart --- .../services/result-selection.store.ts | 5 +- .../time-series-chart.component.html | 2 +- .../time-series-chart.component.ts | 62 ++++++++++++++++--- .../services/line-chart.service.ts | 11 ++-- 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/frontend/src/app/modules/result-selection/services/result-selection.store.ts b/frontend/src/app/modules/result-selection/services/result-selection.store.ts index 7d63285587..3bbdd0cb04 100644 --- a/frontend/src/app/modules/result-selection/services/result-selection.store.ts +++ b/frontend/src/app/modules/result-selection/services/result-selection.store.ts @@ -55,7 +55,7 @@ export class ResultSelectionStore { validQuery = false; - oldToNewChartKeyMap: {[key: string]: string} = { + private readonly oldToNewChartKeyMap: {[key: string]: string} = { // General selectedFolder: 'jobGroupIds', selectedPages: 'pageIds', @@ -64,9 +64,6 @@ export class ResultSelectionStore { selectedLocations: 'locationIds', // Time series - comparativeFrom: 'fromComparative', - comparativeTo: 'toComparative', - selectedTimeFrameInterval: 'interval', trimAboveLoadTimes: 'maxLoadTimes', trimAboveRequestCounts: 'maxRequestCounts', trimAboveRequestSizes: 'maxRequestSizes', diff --git a/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.html b/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.html index 9a2212c187..cdd98b3140 100644 --- a/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.html +++ b/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.html @@ -45,7 +45,7 @@

{{ "frontend.de.iteratec.chart.errorHeader" | translate }}

{{ "frontend.de.iteratec.chart.datapointSelection.error.multipleServer" | translate }}
-
diff --git a/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.ts b/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.ts index 9eba709d58..be89c4c1e7 100644 --- a/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.ts +++ b/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.ts @@ -14,7 +14,8 @@ import {EventResultData} from '../../models/event-result-data.model'; import {LineChartService} from '../../services/line-chart.service'; import {NgxSmartModalService} from 'ngx-smart-modal'; import {SpinnerService} from '../../../shared/services/spinner.service'; -import {TranslateService} from '@ngx-translate/core'; +import {ActivatedRoute, Params} from '@angular/router'; +import {ResultSelectionStore} from '../../../result-selection/services/result-selection.store'; @Component({ @@ -33,8 +34,6 @@ export class TimeSeriesChartComponent implements AfterContentInit, OnChanges { @ViewChild('svg') svgElement: ElementRef; - public ngxSmartModalService; - dataTrimLabels: { [key: string]: string } = {}; dataTrimInputRange: { [key: string]: { [key: string]: number } } = {min: {}, max: {}}; dataTrimInputStep: { [key: string]: number } = {}; @@ -46,12 +45,13 @@ export class TimeSeriesChartComponent implements AfterContentInit, OnChanges { constructor(private lineChartService: LineChartService, private spinnerService: SpinnerService, - private translateService: TranslateService, - ngxSmartModalService: NgxSmartModalService) { - this.ngxSmartModalService = ngxSmartModalService; + private resultSelectionStore: ResultSelectionStore, + private ngxSmartModalService: NgxSmartModalService, + private route: ActivatedRoute) { } ngAfterContentInit(): void { + this.readAdditionalQueryParams(); this.lineChartService.initChart(this.svgElement, () => this.handlePointSelectionError()); } @@ -88,6 +88,7 @@ export class TimeSeriesChartComponent implements AfterContentInit, OnChanges { return; } + this.writeQueryWithAdditionalParams(); const timeSeries = this.lineChartService.prepareData(this.timeSeriesResults, this.selectedTrimValues); this.lineChartService.prepareLegend(this.timeSeriesResults); this.lineChartService.drawLineChart(timeSeries, this.timeSeriesResults.measurandGroups, @@ -102,6 +103,7 @@ export class TimeSeriesChartComponent implements AfterContentInit, OnChanges { return; } + this.writeQueryWithAdditionalParams(); const timeSeries = this.lineChartService.prepareData(this.timeSeriesResults, this.selectedTrimValues); this.lineChartService.drawLineChart(timeSeries, this.timeSeriesResults.measurandGroups, this.timeSeriesResults.summaryLabels, this.timeSeriesResults.numberOfTimeSeries, this.selectedTrimValues); @@ -110,10 +112,6 @@ export class TimeSeriesChartComponent implements AfterContentInit, OnChanges { this.spinnerService.hideSpinner('time-series-line-chart-spinner'); } - handlePointSelectionError(): void { - this.ngxSmartModalService.open('pointSelectionErrorModal'); - } - adjustInputByEvent(event, selectedInput: string, otherInput: string, measurandGroup: string): void { if (event.inputType !== 'insertText' && !event.inputType.startsWith('delete')) { this.considerMaxInputTmpRange(selectedInput, measurandGroup); @@ -151,6 +149,50 @@ export class TimeSeriesChartComponent implements AfterContentInit, OnChanges { } } + closePointSelectionErrorModal(): void { + this.ngxSmartModalService.close('pointSelectionErrorModal'); + } + + private handlePointSelectionError(): void { + this.ngxSmartModalService.open('pointSelectionErrorModal'); + } + + private readAdditionalQueryParams(): void { + this.route.queryParams.subscribe((params: Params) => { + this.selectedTrimValues.min['LOAD_TIMES'] = params.minLoadTimes ? + params.minLoadTimes : this.selectedTrimValues.min['LOAD_TIMES']; + this.selectedTrimValues.max['LOAD_TIMES'] = params.maxLoadTimes ? + params.maxLoadTimes : this.selectedTrimValues.max['LOAD_TIMES']; + this.selectedTrimValues.min['PERCENTAGES'] = params.minPercentages ? + params.minPercentages : this.selectedTrimValues.min['PERCENTAGES']; + this.selectedTrimValues.max['PERCENTAGES'] = params.maxPercentages ? + params.maxPercentages : this.selectedTrimValues.max['PERCENTAGES']; + this.selectedTrimValues.min['REQUEST_COUNTS'] = params.minRequestCounts ? + params.minRequestCounts : this.selectedTrimValues.min['REQUEST_COUNTS']; + this.selectedTrimValues.max['REQUEST_COUNTS'] = params.maxRequestCounts ? + params.maxRequestCounts : this.selectedTrimValues.max['REQUEST_COUNTS']; + this.selectedTrimValues.min['REQUEST_SIZES'] = params.minRequestSizes ? + params.minRequestSizes : this.selectedTrimValues.min['REQUEST_SIZES']; + this.selectedTrimValues.max['REQUEST_SIZES'] = params.maxRequestSizes ? + params.maxRequestSizes : this.selectedTrimValues.max['REQUEST_SIZES']; + }); + } + + private writeQueryWithAdditionalParams(): void { + const additionalParams: Params = { + minLoadTimes: this.selectedTrimValues.min['LOAD_TIMES'] ? this.selectedTrimValues.min['LOAD_TIMES'] : null, + maxLoadTimes: this.selectedTrimValues.max['LOAD_TIMES'] ? this.selectedTrimValues.max['LOAD_TIMES'] : null, + minPercentages: this.selectedTrimValues.min['PERCENTAGES'] ? this.selectedTrimValues.min['PERCENTAGES'] : null, + maxPercentages: this.selectedTrimValues.max['PERCENTAGES'] ? this.selectedTrimValues.max['PERCENTAGES'] : null, + minRequestCounts: this.selectedTrimValues.min['REQUEST_COUNTS'] ? this.selectedTrimValues.min['REQUEST_COUNTS'] : null, + maxRequestCounts: this.selectedTrimValues.max['REQUEST_COUNTS'] ? this.selectedTrimValues.max['REQUEST_COUNTS'] : null, + minRequestSizes: this.selectedTrimValues.min['REQUEST_SIZES'] ? this.selectedTrimValues.min['REQUEST_SIZES'] : null, + maxRequestSizes: this.selectedTrimValues.max['REQUEST_SIZES'] ? this.selectedTrimValues.max['REQUEST_SIZES'] : null, + }; + + this.resultSelectionStore.writeQueryParams(additionalParams); + } + private setDataTrimSettings(): void { this.dataTrimLabels = this.lineChartService.dataTrimLabels; const dataMaxValues = this.lineChartService.dataMaxValues; diff --git a/frontend/src/app/modules/time-series/services/line-chart.service.ts b/frontend/src/app/modules/time-series/services/line-chart.service.ts index 8a6a621c06..57208e9334 100644 --- a/frontend/src/app/modules/time-series/services/line-chart.service.ts +++ b/frontend/src/app/modules/time-series/services/line-chart.service.ts @@ -37,8 +37,8 @@ export class LineChartService { // D3 margin conventions // > With this convention, all subsequent code can ignore margins. // see: https://bl.ocks.org/mbostock/3019563 - private MARGIN: { [key: string]: number } = {top: 60, right: 60, bottom: 40, left: 75}; - private Y_AXIS_WIDTH = 65; + private readonly MARGIN: { [key: string]: number } = {top: 60, right: 60, bottom: 40, left: 75}; + private readonly Y_AXIS_WIDTH = 65; private _margin: { [key: string]: number } = { top: this.MARGIN.top, @@ -51,6 +51,9 @@ export class LineChartService { private _legendGroupTop: number = this._margin.top + this._height + 50; private _xScale: D3ScaleTime; + private _dataTrimLabels: { [key: string]: string } = {}; + private _dataMaxValues: { [key: string]: number } = {}; + constructor(private translationService: TranslateService, private urlBuilderService: UrlBuilderService, private lineChartScaleService: LineChartScaleService, @@ -59,14 +62,10 @@ export class LineChartService { private lineChartLegendService: LineChartLegendService) { } - private _dataTrimLabels: { [key: string]: string } = {}; - get dataTrimLabels(): { [p: string]: string } { return this._dataTrimLabels; } - private _dataMaxValues: { [key: string]: number } = {}; - get dataMaxValues(): { [p: string]: number } { return this._dataMaxValues; } From 2a77919a08659941e84c9937c2368a83a15e60f8 Mon Sep 17 00:00:00 2001 From: Daniel Steger Date: Wed, 24 Jun 2020 12:54:52 +0200 Subject: [PATCH 4/4] Fix test --- .../time-series-chart/time-series-chart.component.spec.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.spec.ts b/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.spec.ts index 0d6b271e36..447b1719ee 100644 --- a/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.spec.ts +++ b/frontend/src/app/modules/time-series/components/time-series-chart/time-series-chart.component.spec.ts @@ -2,6 +2,8 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {TimeSeriesChartComponent} from './time-series-chart.component'; import {SharedMocksModule} from '../../../../testing/shared-mocks.module'; import {SharedModule} from '../../../shared/shared.module'; +import {ResultSelectionStore} from '../../../result-selection/services/result-selection.store'; +import {ResultSelectionService} from '../../../result-selection/services/result-selection.service'; describe('TimeSeriesChartComponent', () => { let component: TimeSeriesChartComponent; @@ -10,7 +12,8 @@ describe('TimeSeriesChartComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [TimeSeriesChartComponent], - imports: [SharedMocksModule, SharedModule] + imports: [SharedMocksModule, SharedModule], + providers: [ResultSelectionStore, ResultSelectionService] }) .compileComponents(); }));