This is an automated email from the ASF dual-hosted git repository. zehnder pushed a commit to branch STREAMPIPES-234 in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
commit acd61fee92e76d6caea1b0ea7dd215171625df87 Author: Philipp Zehnder <[email protected]> AuthorDate: Tue Oct 27 11:19:39 2020 +0100 Time-series explorer supports now new label colors --- .../datalake/datalake-rest.service.ts | 2 +- ui/src/app/core-ui/core-ui.module.ts | 5 +- .../image-categorize/image-categorize.component.ts | 2 +- .../configure-labels.component.html | 2 +- .../configure-labels/configure-labels.component.ts | 12 ++ .../labels/components/labels/labels.component.css | 0 .../labels/components/labels/labels.component.html | 9 - .../labels/components/labels/labels.component.ts | 17 -- .../select-label/select-label.component.html | 39 +++-- .../select-label/select-label.component.ts | 12 +- .../app/core-ui/labels/services/label.service.ts | 28 ++- .../data-explorer-dashboard-widget.component.html | 2 +- .../data-explorer-dashboard-widget.component.ts | 2 + .../widgets/base/base-data-explorer-widget.ts | 14 +- .../line-chart/line-chart-widget.component.html | 14 +- .../line-chart/line-chart-widget.component.ts | 191 ++++++++++++++------- 16 files changed, 216 insertions(+), 135 deletions(-) diff --git a/ui/src/app/core-services/datalake/datalake-rest.service.ts b/ui/src/app/core-services/datalake/datalake-rest.service.ts index a78631a..fee644f 100644 --- a/ui/src/app/core-services/datalake/datalake-rest.service.ts +++ b/ui/src/app/core-services/datalake/datalake-rest.service.ts @@ -105,7 +105,7 @@ export class DatalakeRestService { } get_timeseries_labels() { - // mocked labels + // mocked colorPropertyStringValues const labels = { coffee: ['coffee', 'coffee special', 'espresso', '2x espresso', 'hot water', 'undefined'], state: ['online', 'offline', 'active', 'inactive'], diff --git a/ui/src/app/core-ui/core-ui.module.ts b/ui/src/app/core-ui/core-ui.module.ts index 29dbce2..1ffc90b 100644 --- a/ui/src/app/core-ui/core-ui.module.ts +++ b/ui/src/app/core-ui/core-ui.module.ts @@ -75,7 +75,6 @@ import { CodemirrorModule } from '@ctrl/ngx-codemirror'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { ConfigureLabelsComponent } from './labels/components/configure-labels/configure-labels.component'; import { LabelListItemComponent } from './labels/components/label-list-item/label-list-item.component'; -import { LabelsComponent } from './labels/components/labels/labels.component'; @NgModule({ imports: [ @@ -129,7 +128,6 @@ import { LabelsComponent } from './labels/components/labels/labels.component'; StaticRuntimeResolvableAnyInputComponent, StaticRuntimeResolvableOneOfInputComponent, LabelListItemComponent, - LabelsComponent, ], providers: [ MatDatepickerModule, @@ -169,8 +167,7 @@ import { LabelsComponent } from './labels/components/labels/labels.component'; StaticOneOfInputComponent, StaticRuntimeResolvableAnyInputComponent, StaticRuntimeResolvableOneOfInputComponent, - ImageViewerComponent, - LabelsComponent + ImageViewerComponent ] }) export class CoreUiModule { diff --git a/ui/src/app/core-ui/image/image-categorize/image-categorize.component.ts b/ui/src/app/core-ui/image/image-categorize/image-categorize.component.ts index dac99d0..07507d4 100644 --- a/ui/src/app/core-ui/image/image-categorize/image-categorize.component.ts +++ b/ui/src/app/core-ui/image/image-categorize/image-categorize.component.ts @@ -49,7 +49,7 @@ export class ImageCategorizeComponent implements OnInit, AfterViewInit { constructor(private restService: DatalakeRestService, public colorService: ColorService, private snackBar: MatSnackBar) { } ngOnInit(): void { - // TODO: Load labels for images + // TODO: Load colorPropertyStringValues for images this.selectedLabels = []; // TODO: Get Labels diff --git a/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.html b/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.html index 1e85365..bd0fb7e 100644 --- a/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.html +++ b/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.html @@ -2,7 +2,7 @@ <div *ngIf="!editCategory"> <h2>Categories</h2> - <mat-form-field style="margin-top: -15px; margin-bottom: -10px"> + <mat-form-field *ngIf="!noCategoriesAvailable" style="margin-top: -15px; margin-bottom: -10px"> <mat-label>Select Label Category</mat-label> <mat-select [(value)]="selectedCategory" (selectionChange)="startEditCategory($event)"> <mat-option value="internal_placeholder"></mat-option> diff --git a/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.ts b/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.ts index c0d9f65..14fdce9 100644 --- a/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.ts +++ b/ui/src/app/core-ui/labels/components/configure-labels/configure-labels.component.ts @@ -22,10 +22,13 @@ export class ConfigureLabelsComponent implements OnInit { public editCategory: boolean; + public noCategoriesAvailable = true; + ngOnInit(): void { this.editCategory = false; this.labelService.getCategories().subscribe(res => { this.categories = res; + this.setCategoryAvailable(); }); } @@ -53,11 +56,20 @@ export class ConfigureLabelsComponent implements OnInit { this.selectedCategory = res; this.editCategory = true; this.categories.push(res); + this.setCategoryAvailable(); }); this.categoryLabels = []; } + setCategoryAvailable() { + if (this.categories.length > 0) { + this.noCategoriesAvailable = false; + } else { + this.noCategoriesAvailable = true; + } + } + updateCategory(newCategoryName) { this.selectedCategory.name = newCategoryName; diff --git a/ui/src/app/core-ui/labels/components/labels/labels.component.css b/ui/src/app/core-ui/labels/components/labels/labels.component.css deleted file mode 100644 index e69de29..0000000 diff --git a/ui/src/app/core-ui/labels/components/labels/labels.component.html b/ui/src/app/core-ui/labels/components/labels/labels.component.html deleted file mode 100644 index 25b0c6d..0000000 --- a/ui/src/app/core-ui/labels/components/labels/labels.component.html +++ /dev/null @@ -1,9 +0,0 @@ -<sp-configure-labels *ngIf="editLabels"></sp-configure-labels> - -<sp-select-label - *ngIf="!editLabels" - [labels]="possibleLabels" - [enableShortCuts]="true" - (labelChange)="handleLabelChange($event)"> -</sp-select-label> - diff --git a/ui/src/app/core-ui/labels/components/labels/labels.component.ts b/ui/src/app/core-ui/labels/components/labels/labels.component.ts deleted file mode 100644 index 8287ede..0000000 --- a/ui/src/app/core-ui/labels/components/labels/labels.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'sp-labels', - templateUrl: './labels.component.html', - styleUrls: ['./labels.component.css'] -}) -export class LabelsComponent implements OnInit { - - public editLabels = false; - - constructor() { } - - ngOnInit(): void { - } - -} diff --git a/ui/src/app/core-ui/labels/components/select-label/select-label.component.html b/ui/src/app/core-ui/labels/components/select-label/select-label.component.html index 48fa1a4..9c2484e 100644 --- a/ui/src/app/core-ui/labels/components/select-label/select-label.component.html +++ b/ui/src/app/core-ui/labels/components/select-label/select-label.component.html @@ -18,23 +18,26 @@ <div fxLayout="column" fxLayoutAlign="space-around center"> <h2>Labels</h2> - <div style="padding-left: 5px; padding-right: 5px; border-radius: 50px; font-size: 20px;"> - <mat-form-field style="margin-top: -15px; margin-bottom: -10px"> - <mat-select (selectionChange)="changeCategory($event)" [(value)]="selectedCategory"> - <mat-option *ngFor="let category of categories" [value]="category"> - {{category.name}} - </mat-option> - </mat-select> - </mat-form-field> - </div> - <mat-list> - <mat-list-item *ngFor="let label of labels; index as i" - [style.background-color]="selectedLabel.name == label.name ? 'lightgrey' : 'white'" - style="height: 30px; padding-top: 5px; padding-buttom: 5px; border-radius: 50px; margin-bottom: 5px" - (click)="selectLabel(label)"> + <div *ngIf="noCategories">There are no labels available!</div> + <div *ngIf="!noCategories"> + <div style="padding-left: 5px; padding-right: 5px; border-radius: 50px; font-size: 20px;"> + <mat-form-field style="margin-top: -15px; margin-bottom: -10px"> + <mat-select (selectionChange)="changeCategory($event.value)" [(value)]="selectedCategory"> + <mat-option *ngFor="let category of categories" [value]="category"> + {{category.name}} + </mat-option> + </mat-select> + </mat-form-field> + </div> + <mat-list> + <mat-list-item *ngFor="let label of labels; index as i" + [style.background-color]="selectedLabel.name == label.name ? 'lightgrey' : 'white'" + style="height: 30px; padding-top: 5px; padding-buttom: 5px; border-radius: 50px; margin-bottom: 5px" + (click)="selectLabel(label)"> - <mat-icon matListIcon [style.color]="label.color" style="margin-top: -8px;">color_lens</mat-icon> - <h4 style="margin-top: -3px;"> {{label.name}} <label *ngIf="i < 10"> #{{i+1}}</label> </h4> - </mat-list-item> - </mat-list> + <mat-icon matListIcon [style.color]="label.color" style="margin-top: -8px;">color_lens</mat-icon> + <h4 style="margin-top: -3px;"> {{label.name}} <label *ngIf="i < 10"> #{{i+1}}</label> </h4> + </mat-list-item> + </mat-list> + </div> </div> \ No newline at end of file diff --git a/ui/src/app/core-ui/labels/components/select-label/select-label.component.ts b/ui/src/app/core-ui/labels/components/select-label/select-label.component.ts index c673856..d6c3db8 100644 --- a/ui/src/app/core-ui/labels/components/select-label/select-label.component.ts +++ b/ui/src/app/core-ui/labels/components/select-label/select-label.component.ts @@ -37,18 +37,26 @@ export class SelectLabelComponent implements OnInit { public labels: Label[]; public selectedLabel: Label; + public noCategories = true; + constructor(public labelService: LabelService, public colorService: ColorService) { } ngOnInit(): void { this.labelService.getCategories().subscribe(res => { + this.categories = res; + if (this.categories.length > 0) { + this.noCategories = false; + this.selectedCategory = res[0]; + this.changeCategory(this.selectedCategory); + } }); } changeCategory(c) { - this.labelService.getLabelsOfCategory(c.value).subscribe(res => { + this.labelService.getLabelsOfCategory(c).subscribe(res => { this.labels = res; - this.selectedLabel = this.labels[0]; + this.selectLabel(this.labels[0]); }); } diff --git a/ui/src/app/core-ui/labels/services/label.service.ts b/ui/src/app/core-ui/labels/services/label.service.ts index df60325..14ac09f 100644 --- a/ui/src/app/core-ui/labels/services/label.service.ts +++ b/ui/src/app/core-ui/labels/services/label.service.ts @@ -2,13 +2,13 @@ import { Injectable } from '@angular/core'; import { Category, Label } from '../../../core-model/gen/streampipes-model'; import { PlatformServicesCommons } from '../../../platform-services/apis/commons.service'; import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; +import { Observable, ReplaySubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class LabelService { - private categories = []; + private bufferedLabels = []; urlBase() { return this.platformServicesCommons.authUserBasePath(); @@ -38,6 +38,30 @@ export class LabelService { return this.$http.delete(this.urlBase() + '/labeling/category/' + c._id); } + getAllLabels() { + return this.$http.get(this.urlBase() + '/labeling/label/'); + } + + getLabel(labelId: string) { + return this.$http.get(this.urlBase() + '/labeling/label/' + labelId); + } + + getBufferedLabel(labelId: string) { + // this.bufferedLabels + const result = new ReplaySubject(1); + + if (this.bufferedLabels[labelId] !== undefined) { + result.next(this.bufferedLabels[labelId]); + } else { + this.getLabel(labelId).subscribe(label => { + this.bufferedLabels.push({labelId: label}); + result.next(label); + }); + } + + return result; + } + addLabel(l: Label) { return this.$http.post(this.urlBase() + '/labeling/label', l); } diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html index e96e263..f0df458 100644 --- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html +++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html @@ -20,7 +20,7 @@ <div class="box"> <div class="assemblyOptions sp-blue-bg m-0 row header h-40" *ngIf="editMode"> <div fxFlex="100" layout="row" fxLayoutAlign="start center"> - {{this.configuredWidget.dataLakeMeasure.measureName}} + {{ title }} </div> <div fxFlex="100" layout="row" fxLayoutAlign="end center"> <button mat-icon-button matTooltip="Download data" class="icon" (click)="downloadDataAsFile()" color="white"> diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts index b72abdb..2b30366 100644 --- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts +++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts @@ -54,6 +54,7 @@ export class DataExplorerDashboardWidgetComponent implements OnInit { @Output() deleteCallback: EventEmitter<IDataViewDashboardItem> = new EventEmitter<IDataViewDashboardItem>(); @Output() updateCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>(); + title = ''; widgetLoaded = false; configuredWidget: DataExplorerWidgetModel; @@ -65,6 +66,7 @@ export class DataExplorerDashboardWidgetComponent implements OnInit { this.dataViewDataExplorerService.getWidget(this.widget.id).subscribe(response => { this.configuredWidget = response; this.widgetLoaded = true; + this.title = this.configuredWidget.dataLakeMeasure.measureName; }); } diff --git a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.ts b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.ts index 72c0eb7..b67e30d 100644 --- a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.ts +++ b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.ts @@ -111,19 +111,21 @@ export abstract class BaseDataExplorerWidget implements OnChanges { return result; } - getNonNumericProperties(eventSchema: EventSchema) { + getNoneNumericProperties(eventSchema: EventSchema) { const result: EventPropertyUnion[] = []; + const b = new EventPropertyPrimitive(); + b["@class"] = "org.apache.streampipes.model.schema.EventPropertyPrimitive"; + b.runtimeType = 'https://www.w3.org/2001/XMLSchema#string'; + b.runtimeName = ''; + + result.push(b); + eventSchema.eventProperties.forEach(p => { if (!(p.domainProperties.some(dp => dp === 'http://schema.org/DateTime')) && !this.isNumber(p)) { result.push(p); } }); - const b = new EventPropertyPrimitive(); - b["@class"] = "org.apache.streampipes.model.schema.EventPropertyPrimitive"; - b.runtimeType = 'https://www.w3.org/2001/XMLSchema#string'; - b.runtimeName = 'sp_internal_label'; - result.push(b); return result; } diff --git a/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.html b/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.html index 3a5e3b0..88fdb35 100644 --- a/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.html +++ b/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.html @@ -24,19 +24,19 @@ label="Select Properties" multiple = true style="margin-right: 10px;" - (changeSelectedProperties)="setSelectedColumn($event)" - [availableProperties]="availableColumns" - [selectedProperties]="selectedColumns"> + (changeSelectedProperties)="setSelectedProperties($event)" + [availableProperties]="availableProperties" + [selectedProperties]="selectedLineChartProperties"> </sp-select-properties> <sp-select-properties - label="Select String Property" + label="Select Background Color" multiple = false style="margin-right: 10px;" - *ngIf="showLabelColumnSelection" - (changeSelectedProperties)="setSelectedLabelColumn($event)" + *ngIf="showBackgroundColorProperty" + (changeSelectedProperties)="setSelectedBackgroundColorProperty($event)" [availableProperties]="availableNoneNumericColumns" - [selectedProperties]="selectedNonNumericColumn"> + [selectedProperties]="selectedBackgroundColorProperty"> </sp-select-properties> <sp-aggregate-configuration *ngIf="advancedSettingsActive" diff --git a/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.ts b/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.ts index 61fc733..c125a84 100644 --- a/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.ts +++ b/ui/src/app/data-explorer/components/widgets/line-chart/line-chart-widget.component.ts @@ -23,8 +23,9 @@ import { GroupedDataResult } from '../../../../core-model/datalake/GroupedDataRe import { DatalakeRestService } from '../../../../core-services/datalake/datalake-rest.service'; import { ColorService } from './services/color.service'; import { BaseDataExplorerWidget } from '../base/base-data-explorer-widget'; -import { EventPropertyUnion } from '../../../../core-model/gen/streampipes-model'; +import { EventPropertyUnion, Label } from '../../../../core-model/gen/streampipes-model'; import { ResizeService } from '../../../services/resize.service'; +import { LabelService } from '../../../../core-ui/labels/services/label.service'; @Component({ selector: 'sp-data-explorer-line-chart-widget', @@ -34,19 +35,19 @@ import { ResizeService } from '../../../services/resize.service'; export class LineChartWidgetComponent extends BaseDataExplorerWidget implements OnInit { data: any[] = undefined; - labels: any[] = undefined; - availableColumns: EventPropertyUnion[] = []; + colorPropertyStringValues: any[] = undefined; + availableProperties: EventPropertyUnion[] = []; availableNoneNumericColumns: EventPropertyUnion[] = []; - selectedColumns: EventPropertyUnion[] = []; - selectedNonNumericColumn: EventPropertyUnion = undefined; + selectedLineChartProperties: EventPropertyUnion[] = []; + selectedBackgroundColorProperty: EventPropertyUnion = undefined; dimensionProperties: EventPropertyUnion[] = []; yKeys: string[] = []; xKey: string; - private nonNumericKey: string = undefined; + private backgroundColorPropertyKey: string = undefined; advancedSettingsActive = false; - showLabelColumnSelection = true; + showBackgroundColorProperty = true; selectedStartX = undefined; selectedEndX = undefined; @@ -67,7 +68,8 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements public colorService: ColorService, public renderer: Renderer2, protected dataLakeRestService: DatalakeRestService, - private resizeService: ResizeService) { + private resizeService: ResizeService, + public labelService: LabelService ) { super(dataLakeRestService, dialog); } @@ -139,14 +141,14 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements ngOnInit(): void { - this.availableColumns = this.getNumericProperty(this.dataExplorerWidget.dataLakeMeasure.eventSchema); + this.availableProperties = this.getNumericProperty(this.dataExplorerWidget.dataLakeMeasure.eventSchema); this.dimensionProperties = this.getDimensionProperties(this.dataExplorerWidget.dataLakeMeasure.eventSchema); - this.availableNoneNumericColumns = this.getNonNumericProperties(this.dataExplorerWidget.dataLakeMeasure.eventSchema); + this.availableNoneNumericColumns = this.getNoneNumericProperties(this.dataExplorerWidget.dataLakeMeasure.eventSchema); // Reduce selected columns when more then 6 - this.selectedColumns = this.availableColumns.length > 6 ? this.availableColumns.slice(0, 5) : this.availableColumns; + this.selectedLineChartProperties = this.availableProperties.length > 6 ? this.availableProperties.slice(0, 5) : this.availableProperties; this.xKey = this.getTimestampProperty(this.dataExplorerWidget.dataLakeMeasure.eventSchema).runtimeName; - this.yKeys = this.getRuntimeNames(this.selectedColumns); + this.yKeys = this.getRuntimeNames(this.selectedLineChartProperties); this.updateData(); this.resizeService.resizeSubject.subscribe(info => { if (info.gridsterItem.id === this.gridsterItem.id) { @@ -166,8 +168,8 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements this.dataLakeRestService.getDataAutoAggregation( this.dataExplorerWidget.dataLakeMeasure.measureName, this.viewDateRange.startDate.getTime(), this.viewDateRange.endDate.getTime()) .subscribe((res: DataResult) => { - this.processNoneGroupedData(res); - }); + this.processNoneGroupedData(res); + }); } else { if (this.groupValue === 'None') { this.setShownComponents(false, false, true); @@ -175,15 +177,15 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements this.dataExplorerWidget.dataLakeMeasure.measureName, this.viewDateRange.startDate.getTime(), this.viewDateRange.endDate.getTime() , this.aggregationTimeUnit, this.aggregationValue) .subscribe((res: DataResult) => { - this.processNoneGroupedData(res); - }); + this.processNoneGroupedData(res); + }); } else { this.dataLakeRestService.getGroupedData( this.dataExplorerWidget.dataLakeMeasure.measureName, this.viewDateRange.startDate.getTime(), this.viewDateRange.endDate.getTime(), this.aggregationTimeUnit, this.aggregationValue, this.groupValue) .subscribe((res: GroupedDataResult) => { this.processGroupedData(res); - }); + }); } } } @@ -195,8 +197,12 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements res.measureName = this.dataExplorerWidget.dataLakeMeasure.measureName; const tmp = this.transformData(res, this.xKey); this.data = this.displayData(tmp, this.yKeys); - this.labels = this.loadLabels(tmp, this.nonNumericKey); - this.addLabelsToGraph(this.data, this.labels); + + if (this.labelingModeOn) { + this.backgroundColorPropertyKey = 'sp_internal_label'; + } + this.colorPropertyStringValues = this.loadBackgroundColor(tmp, this.backgroundColorPropertyKey); + this.addBackgroundColorToGraph(this.data, this.colorPropertyStringValues, this.backgroundColorPropertyKey); this.data['measureName'] = tmp.measureName; this.setShownComponents(false, true, false); @@ -210,8 +216,9 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements const tmp = this.transformGroupedData(res, this.xKey); this.data = this.displayGroupedData(tmp); - if (this.data !== undefined && this.data['labels'] !== undefined && this.data['labels'].length > 0) { - this.addInitialColouredShapesToGraph(); + if (this.data !== undefined && + this.data['colorPropertyStringValues'] !== undefined && this.data['colorPropertyStringValues'].length > 0) { + this.addInitialColouredShapesToGraph(this.colorPropertyStringValues, this.colorService.getColor); } this.setShownComponents(false, true, false); @@ -236,11 +243,11 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements } } - loadLabels(transformedData: DataResult, labelKey: string) { + loadBackgroundColor(transformedData: DataResult, backgroundColorKey: string) { let labels; - if (labelKey !== undefined) { + if (backgroundColorKey !== undefined) { transformedData.rows.forEach(serie => { - if (serie.name === labelKey) { + if (serie.name === backgroundColorKey) { labels = serie.y; } }); @@ -248,19 +255,64 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements return labels; } - addLabelsToGraph(data, labels) { - data.forEach(serie => { - // adding customdata property in order to store labels in graph - if (labels !== undefined && labels.length !== 0) { - serie['customdata'] = labels; - this.addInitialColouredShapesToGraph(); + addBackgroundColorToGraph(data, colorPropertyStringValues, backgroundColorPropertyKey) { + + // the all labels function is required to get the correct color and internal name for labeled data + this.labelService.getAllLabels().subscribe((res: Label[]) => { + // holds all labels + const bufferedLabels = {}; + + for (const l of res) { + bufferedLabels[l._id] = l; + } + + const newColorPropertyStringValues = []; + if (colorPropertyStringValues !== undefined && colorPropertyStringValues.length !== 0) { + for (const c of colorPropertyStringValues) { + if (this.labelingModeOn) { + if (c === '') { + newColorPropertyStringValues.push(c); + } else { + newColorPropertyStringValues.push(bufferedLabels[c].name); + } + } else { + newColorPropertyStringValues.push(c); + } + } + } + + // define the function that defines the colors + let colorFunction; + if (this.labelingModeOn) { + colorFunction = ((id) => { + if (id === '') { + return '#FFFFFF'; + } else { + return bufferedLabels[id].color; + } + }); } else { - serie['customdata'] = Array(serie['x'].length).fill(''); + colorFunction = this.colorService.getColor; } - // adding custom hovertemplate in order to display labels in graph - serie['hovertemplate'] = 'y: %{y}<br>' + 'x: %{x}<br>' + this.nonNumericKey + ': %{customdata}'; + + // Add labes and colors for each series of the line chart + data.forEach(serie => { + // add custom data property in order to store colorPropertyStringValues in graph + if (newColorPropertyStringValues !== undefined && newColorPropertyStringValues.length !== 0) { + serie['customdata'] = newColorPropertyStringValues; + // TODO fix this and continue here + + serie['hovertemplate'] = 'y: %{y}<br>' + 'x: %{x}<br>' + backgroundColorPropertyKey + ': %{customdata}'; + this.addInitialColouredShapesToGraph(colorPropertyStringValues, colorFunction); + } else { + serie['customdata'] = Array(serie['x'].length).fill(''); + serie['hovertemplate'] = 'y: %{y}<br>' + 'x: %{x}'; + } + // adding custom hovertemplate in order to display colorPropertyStringValues in graph + }); + this.data = data; + }); - this.data = data; } displayGroupedData(transformedData: GroupedDataResult) { @@ -353,15 +405,20 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements return data; } - setSelectedColumn(selectedColumns: EventPropertyUnion[]) { - this.selectedColumns = selectedColumns; + setSelectedProperties(selectedColumns: EventPropertyUnion[]) { + this.selectedLineChartProperties = selectedColumns; this.yKeys = this.getRuntimeNames(selectedColumns); this.updateData(); } - setSelectedLabelColumn(selectedLabelColumn: EventPropertyUnion) { - this.selectedNonNumericColumn = selectedLabelColumn; - this.nonNumericKey = selectedLabelColumn.runtimeName; + setSelectedBackgroundColorProperty(selectedBackgroundColorProperty: EventPropertyUnion) { + if (selectedBackgroundColorProperty.runtimeName === '') { + this.selectedBackgroundColorProperty = undefined; + this.backgroundColorPropertyKey = undefined; + } else { + this.selectedBackgroundColorProperty = selectedBackgroundColorProperty; + this.backgroundColorPropertyKey = selectedBackgroundColorProperty.runtimeName; + } this.updateData(); } @@ -390,7 +447,7 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements this.selectedEndX = allData.x[searchIndex - 1]; - this.saveLabelsInDatabase(this.selectedLabel.name, this.selectedStartX, this.selectedEndX); + this.saveLabelsInDatabase(this.selectedLabel._id, this.selectedStartX, this.selectedEndX); // adding coloured shape (based on selected label) to graph (equals selected time interval) this.addShapeToGraph(this.selectedStartX, this.selectedEndX, this.selectedLabel.color); @@ -420,16 +477,14 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements // updating related global variable this.setNSelectedPoints(selected_points); - // opening Labeling-Dialog - for (const series of this.data) { for (const point of series['selectedpoints']) { - series['customdata'][point] = this.selectedLabel.name; + series['customdata'][point] = this.selectedLabel._id; } } - this.labels = this.data[0]['customdata']; - // saving labels persistently - this.saveLabelsInDatabase(this.selectedLabel.name, this.selectedStartX, this.selectedEndX); + this.colorPropertyStringValues = this.data[0]['customdata']; + // saving colorPropertyStringValues persistently + this.saveLabelsInDatabase(this.selectedLabel._id, this.selectedStartX, this.selectedEndX); // adding coloured shape (based on selected label) to graph (equals selected time interval) this.addShapeToGraph(this.selectedStartX, this.selectedEndX, this.selectedLabel.color); @@ -437,12 +492,11 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements } } - handleLabelChange(label: {category, label}) { + handleLabelChange(label: Label) { this.selectedLabel = label; } toggleLabelingMode() { - // only allowing to activate labeling mode if current graph mode does not equal 'lines' if (this.labelingModeOn) { for (let i = 0; i < this.data.length; i++) { this.data[i]['mode'] = 'lines+markers'; @@ -458,6 +512,7 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements private activateLabelingMode() { const modeBarButtons = document.getElementsByClassName('modebar-btn'); + this.showBackgroundColorProperty = false; for (let i = 0; i < modeBarButtons.length; i++) { if (modeBarButtons[i].getAttribute('data-title') === 'Labeling') { @@ -474,6 +529,9 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements } } + + this.updateData(); + // changing dragmode to 'select' this.graph.layout.dragmode = 'select'; } @@ -498,17 +556,15 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements // changing dragmode to 'zoom' this.graph.layout.dragmode = 'zoom'; + this.showBackgroundColorProperty = true; } private saveLabelsInDatabase(label, start_X, end_X) { const startdate = new Date(start_X).getTime() - 1; const enddate = new Date(end_X).getTime() + 1; - if (this.nonNumericKey === undefined) { - this.nonNumericKey = 'sp_internal_label'; - } - this.dataLakeRestService.saveLabelsInDatabase(this.data['measureName'], this.nonNumericKey, startdate, enddate, label, this.xKey).subscribe( + this.dataLakeRestService.saveLabelsInDatabase(this.data['measureName'], 'sp_internal_label', startdate, enddate, label, this.xKey).subscribe( res => { // TODO add pop up similar to images // console.log('Successfully wrote label ' + currentLabel + ' into database.'); @@ -516,24 +572,27 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements ); } - // TODO change here to change shape color - private addInitialColouredShapesToGraph() { + private addInitialColouredShapesToGraph(newColorPropertyStringValues, getColor) { let selectedLabel = ''; let indices = []; - for (let label = 0; label < this.labels.length; label++) { - if (selectedLabel !== this.labels[label] && indices.length > 0) { - const startdate = new Date(this.data[0]['x'][indices[0]]).getTime(); - const enddate = new Date(this.data[0]['x'][indices[indices.length - 1]]).getTime(); + if (newColorPropertyStringValues !== undefined) { - this.addShapeToGraph(startdate, enddate, this.colorService.getColor(this.labels[label]), true); + for (let label = 0; label < newColorPropertyStringValues.length; label++) { + if (selectedLabel !== newColorPropertyStringValues[label] && indices.length > 0) { + const startdate = new Date(this.data[0]['x'][indices[0]]).getTime(); + const enddate = new Date(this.data[0]['x'][indices[indices.length - 1]]).getTime(); - selectedLabel = undefined; - indices = []; - indices.push(label); - } else { - indices.push(label); + // TODO get color of label and text + this.addShapeToGraph(startdate, enddate, getColor(newColorPropertyStringValues[label - 1]), true); + + selectedLabel = undefined; + indices = []; + indices.push(label); + } else { + indices.push(label); + } + selectedLabel = this.colorPropertyStringValues[label]; } - selectedLabel = this.labels[label]; } } @@ -609,7 +668,7 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget implements } handlingAdvancedToggleChange() { - this.showLabelColumnSelection = !this.showLabelColumnSelection; + this.showBackgroundColorProperty = !this.showBackgroundColorProperty; this.updateData(); }
