Skip to content

Commit 40d4efb

Browse files
committed
Merge remote-tracking branch 'origin/develop' into feature/timeseriesChart
# Conflicts: # frontend/src/app/modules/time-series/services/line-chart.service.ts # grails-app/i18n/messages.properties # grails-app/i18n/messages_de.properties # grails-app/services/de/iteratec/osm/linechart/LineChartTimeSeriesService.groovy
2 parents 3c597cf + 7198e46 commit 40d4efb

File tree

10 files changed

+338
-80
lines changed

10 files changed

+338
-80
lines changed

frontend/src/app/modules/time-series/components/time-series-line-chart/time-series-line-chart.component.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ osm-time-series-line-chart {
6060
}
6161
}
6262

63+
.summary-label-key {
64+
font-weight: bold;
65+
}
66+
67+
.summary-label {
68+
font-weight: normal;
69+
}
70+
6371
.legend-entry {
6472
cursor: pointer;
6573
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import {EventResultSeriesDTO} from './event-result-series.model';
2+
import {SummaryLabel} from "./summary-label.model";
23

34
export interface EventResultDataDTO {
45
series: EventResultSeriesDTO[];
6+
summaryLabels: SummaryLabel[];
57
}
68

79
export class EventResultData implements EventResultDataDTO {
810
series: EventResultSeriesDTO[];
11+
summaryLabels: SummaryLabel[];
912

1013
constructor() {
1114
this.series = [];
15+
this.summaryLabels = [];
1216
}
1317
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface SummaryLabel {
2+
key: string;
3+
label: string;
4+
}

frontend/src/app/modules/time-series/services/line-chart.service.ts

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {getColorScheme} from 'src/app/enums/color-scheme.enum';
4949
import {ChartCommons} from "../../../enums/chart-commons.enum";
5050
import {UrlBuilderService} from "./url-builder.service";
5151
import {PointsSelection} from "../models/points-selection.model";
52+
import {SummaryLabel} from "../models/summary-label.model";
5253

5354
/**
5455
* Generate line charts with ease and fun 😎
@@ -69,10 +70,9 @@ export class LineChartService {
6970
private _height: number = 550 - this._margin.top - this._margin.bottom;
7071
private _labelGroupHeight: number;
7172
private _legendGroupTop: number = this._margin.top + this._height + 50;
72-
private _legendGroupLeft: number = this._margin.left;
73-
private _legendGroupHeight;
74-
private _legendGroupColumnWidth;
75-
private _legendGroupColumns;
73+
private _legendGroupHeight: number;
74+
private _legendGroupColumnWidth: number;
75+
private _legendGroupColumns: number;
7676
private legendDataMap: Object = {};
7777
private brush: BrushBehavior<{}>;
7878
private focusedLegendEntry: string;
@@ -261,6 +261,7 @@ export class LineChartService {
261261
d3Select('.y-axis').transition().call(this.updateYAxis, yScale, this._width, this._margin);
262262

263263
this.addLegendsToChart(chart, incomingData);
264+
this.setSummaryLabel(chart, incomingData.summaryLabels);
264265
this.addDataLinesToChart(chart, xScale, yScale, data);
265266
this.drawAllSelectedPoints();
266267

@@ -298,12 +299,14 @@ export class LineChartService {
298299

299300
let labelDataMap = {};
300301
incomingData.series.forEach((data: EventResultSeriesDTO) => {
301-
let label = data.identifier;
302+
if (incomingData.summaryLabels.length > 0 && incomingData.summaryLabels[0].key != "measurand") {
303+
data.identifier = this.translateMeasurand(data);
304+
}
302305
let key = this.generateKey(data);
303306
labelDataMap[key] = {
304-
text: label,
307+
text: data.identifier,
305308
key: key,
306-
show: true,
309+
show: true
307310
}
308311
});
309312
this.legendDataMap = labelDataMap;
@@ -313,16 +316,18 @@ export class LineChartService {
313316
* Prepares the incoming data for drawing with D3.js
314317
*/
315318
private prepareData(incomingData: EventResultDataDTO): TimeSeries[] {
316-
317319
return incomingData.series.map((data: EventResultSeriesDTO) => {
318320
let lineChartData: TimeSeries = new TimeSeries();
321+
if (incomingData.summaryLabels.length > 0 && incomingData.summaryLabels[0].key != "measurand") {
322+
data.identifier = this.translateMeasurand(data);
323+
}
319324
lineChartData.key = this.generateKey(data);
320325

321326
lineChartData.values = data.data.map((point: EventResultPointDTO) => {
322327
let lineChartDataPoint: TimeSeriesPoint = new TimeSeriesPoint();
323328
lineChartDataPoint.date = parseDate(point.date);
324329
lineChartDataPoint.value = point.value;
325-
lineChartDataPoint.tooltipText = data.jobGroup + ' | ' + data.measuredEvent + ' : '; // TODO Set exact label text when IT-2793 is implemented
330+
lineChartDataPoint.tooltipText = data.identifier + ' : ';
326331
lineChartDataPoint.wptInfo = point.wptInfo;
327332
return lineChartDataPoint;
328333
});
@@ -331,10 +336,21 @@ export class LineChartService {
331336
});
332337
}
333338

339+
private translateMeasurand(data: EventResultSeriesDTO): string {
340+
let splitLabelList: string[] = data.identifier.split(' | ');
341+
let splitLabel: string = this.translationService.instant('frontend.de.iteratec.isr.measurand.' + splitLabelList[0]);
342+
if (!splitLabel.startsWith('frontend.de.iteratec.isr.measurand.')) {
343+
splitLabelList[0] = splitLabel;
344+
}
345+
return splitLabelList.join(' | ');
346+
}
347+
334348
private generateKey(data: EventResultSeriesDTO): string {
335-
return data.jobGroup
336-
+ data.measuredEvent
337-
+ data.data.length;
349+
let key: string = data.identifier.replace(/[^_a-zA-Z0-9-]/g, "");
350+
if (new RegExp('[0-9]').test(key.charAt(0))) {
351+
key = key.replace(/[0-9]/, '_');
352+
}
353+
return key;
338354
}
339355

340356
/**
@@ -347,14 +363,69 @@ export class LineChartService {
347363
.attr('width', this._width + this._margin.left + this._margin.right)
348364
.attr('height', 0);
349365

366+
svg.append('g')
367+
.attr('id', 'header-group')
368+
.attr('transform', `translate(${this._margin.left}, ${this._margin.top - 16})`);
369+
370+
let chart = svg.append('g') // g = grouping element; group all other stuff into the chart
371+
.attr('id', 'time-series-chart-drawing-area')
372+
.attr('transform', `translate(${this._margin.left}, ${this._margin.top})`); // translates the origin to the top left corner (default behavior of D3)
373+
350374
svg.append('g')
351375
.attr('id', 'time-series-chart-legend')
352376
.attr('class', 'legend-group')
353-
.attr('transform', `translate(${this._legendGroupLeft}, ${this._legendGroupTop})`);
377+
.attr('transform', `translate(${this._margin.left}, ${this._legendGroupTop})`);
354378

355-
return svg.append('g') // g = grouping element; group all other stuff into the chart
356-
.attr('id', 'time-series-chart-drawing-area')
357-
.attr('transform', 'translate(' + this._margin.left + ', ' + this._margin.top + ')'); // translates the origin to the top left corner (default behavior of D3)
379+
return chart;
380+
}
381+
382+
private setSummaryLabel(chart: D3Selection<D3BaseType, {}, D3ContainerElement, {}>, summaryLabels: SummaryLabel[]): void {
383+
d3Select('g#header-group').selectAll('.summary-label-text').remove();
384+
if (summaryLabels.length > 0) {
385+
d3Select('#header-group')
386+
.append('g')
387+
.attr('class', 'summary-label-text')
388+
.append('text')
389+
.attr('id', 'summary-label-part0')
390+
.attr('x', this._width / 2)
391+
.attr('text-anchor', 'middle')
392+
.attr('fill', '#555555');
393+
394+
summaryLabels.forEach((summaryLabel: SummaryLabel, index: number) => {
395+
this.translationService
396+
.get('frontend.de.iteratec.osm.timeSeries.chart.label.' + summaryLabel.key)
397+
.pipe(take(1))
398+
.subscribe((key: string) => {
399+
if (summaryLabel.key == 'measurand') {
400+
this.translationService
401+
.get('frontend.de.iteratec.isr.measurand.' + summaryLabel.label)
402+
.pipe(take(1))
403+
.subscribe((label: string) => {
404+
if (label.startsWith('frontend.de.iteratec.isr.measurand.')) {
405+
label = summaryLabel.label
406+
}
407+
label = index < summaryLabels.length - 1 ? `${label} | ` : label;
408+
this.addSummaryLabel(key, label, index);
409+
});
410+
} else {
411+
const label: string = index < summaryLabels.length - 1 ? `${summaryLabel.label} | ` : summaryLabel.label;
412+
this.addSummaryLabel(key, label, index);
413+
}
414+
});
415+
});
416+
chart.selectAll('.summary-label-text').remove();
417+
}
418+
}
419+
420+
private addSummaryLabel(key: string, label: string, index: number): void {
421+
d3Select(`#summary-label-part${index}`)
422+
.append('tspan')
423+
.attr('id', `summary-label-part${index + 1}`)
424+
.attr('class', 'summary-label-key')
425+
.text(`${key}: `)
426+
.append('tspan')
427+
.attr('class', 'summary-label')
428+
.text(label);
358429
}
359430

360431
public startResize(svgElement: ElementRef): void {
@@ -709,7 +780,7 @@ export class LineChartService {
709780
})
710781
// fade in
711782
.transition().duration(500).style('opacity', (timeSeries: TimeSeries) => {
712-
return (this.legendDataMap[timeSeries.key].show) ? '1' : '0.2';
783+
return (this.legendDataMap[timeSeries.key].show) ? '1' : '0.1';
713784
});
714785

715786
return resultingSelection;

grails-app/i18n/messages.properties

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,9 @@ frontend.default.button.save=Save
10691069
frontend.default.button.cancel=Cancel
10701070
frontend.de.iteratec.osm.measurement.setup.title=Measurement Setup
10711071
frontend.de.iteratec.osm.applicationDashboard.kpi.title=Total Customer Satisfaction
1072+
frontend.de.iteratec.isr.measurand.PAGE_CONSTRUCTION_STARTED=Is it happening?
1073+
frontend.de.iteratec.isr.measurand.PAGE_SHOWS_USEFUL_CONTENT=Is it useful?
1074+
frontend.de.iteratec.isr.measurand.PAGE_IS_USABLE=Is it useable?
10721075
frontend.de.iteratec.isr.measurand.DOC_COMPLETE_TIME=Document Complete
10731076
frontend.de.iteratec.isr.measurand.DOM_TIME=DOM Time
10741077
frontend.de.iteratec.isr.measurand.FIRST_BYTE=First Byte
@@ -1288,3 +1291,8 @@ frontend.de.iteratec.chart.contextMenu.deselectPoint=Deselect Point
12881291
frontend.de.iteratec.chart.contextMenu.deselectAllPoints=Deselect all Points
12891292
frontend.de.iteratec.chart.errorHeader=Error
12901293
frontend.de.iteratec.chart.datapointSelection.error.multipleServer=Comparison of the filmstrips is only possible for measurements on the same server.
1294+
frontend.de.iteratec.osm.timeSeries.chart.label.measurand=Measurand
1295+
frontend.de.iteratec.osm.timeSeries.chart.label.application=Application
1296+
frontend.de.iteratec.osm.timeSeries.chart.label.measuredEvent=Measured step
1297+
frontend.de.iteratec.osm.timeSeries.chart.label.location=Location
1298+
frontend.de.iteratec.osm.timeSeries.chart.label.connectivity=Connectivity

grails-app/i18n/messages_de.properties

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,9 @@ frontend.default.button.save=Speichern
10511051
frontend.default.button.cancel=Abbrechen
10521052
frontend.de.iteratec.osm.measurement.setup.title=Setup Messungen
10531053
frontend.de.iteratec.osm.applicationDashboard.kpi.title=Gesamte Kundenzufriedenheit
1054+
frontend.de.iteratec.isr.measurand.PAGE_CONSTRUCTION_STARTED=Is it happening?
1055+
frontend.de.iteratec.isr.measurand.PAGE_SHOWS_USEFUL_CONTENT=Is it useful?
1056+
frontend.de.iteratec.isr.measurand.PAGE_IS_USABLE=Is it useable?
10541057
frontend.de.iteratec.isr.measurand.DOC_COMPLETE_TIME=Document Complete
10551058
frontend.de.iteratec.isr.measurand.DOM_TIME=DOM Time
10561059
frontend.de.iteratec.isr.measurand.FIRST_BYTE=First Byte
@@ -1262,3 +1265,8 @@ frontend.de.iteratec.chart.contextMenu.deselectPoint=Punkt abwählen
12621265
frontend.de.iteratec.chart.contextMenu.deselectAllPoints=Alle Punkte abwählen
12631266
frontend.de.iteratec.chart.errorHeader=Fehler
12641267
frontend.de.iteratec.chart.datapointSelection.error.multipleServer=Vergleich der Filmstreifen ist nur für Messungen des gleichen Servers möglich.
1268+
frontend.de.iteratec.osm.timeSeries.chart.label.measurand=Messgröße
1269+
frontend.de.iteratec.osm.timeSeries.chart.label.application=Anwendung
1270+
frontend.de.iteratec.osm.timeSeries.chart.label.measuredEvent=Messschritt
1271+
frontend.de.iteratec.osm.timeSeries.chart.label.location=Location
1272+
frontend.de.iteratec.osm.timeSeries.chart.label.connectivity=Anbindung

0 commit comments

Comments
 (0)