You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2021/08/22 21:45:36 UTC

[incubator-streampipes] 01/02: [STREAMPIPES-411] Add indicator widget, improve resizing behaviour of widgets

This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit 42a326c56945ab64ce59bc9b305d838f278bc8e2
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Sun Aug 22 23:44:17 2021 +0200

    [STREAMPIPES-411] Add indicator widget, improve resizing behaviour of widgets
---
 .../datalake/DatalakeQueryParameterBuilder.ts      |  18 +++
 .../data-explorer-designer-panel.component.html    |   6 +
 ...ta-explorer-widget-data-settings.component.html |   5 +-
 ...data-explorer-widget-data-settings.component.ts |  16 ---
 .../data-explorer-dashboard-widget.component.html  |  13 +++
 .../widgets/base/base-data-explorer-widget.ts      |   9 +-
 .../widgets/image/image-widget.component.ts        |   8 +-
 .../indicator-chart-widget-config.component.html   |  72 ++++++++++++
 .../indicator-chart-widget-config.component.scss   |  17 +++
 .../indicator-chart-widget-config.component.ts     |  45 ++++++++
 .../indicator-chart-widget.component.html          |  32 ++++++
 .../indicator-chart-widget.component.scss          |  17 +++
 .../indicator/indicator-chart-widget.component.ts  | 126 +++++++++++++++++++++
 .../model/indicator-chart-widget.model.ts          |  30 +++++
 .../line-chart/line-chart-widget.component.ts      |  15 ++-
 .../widgets/table/table-widget.component.ts        |   8 +-
 ui/src/app/data-explorer/data-explorer.module.ts   |  16 +--
 17 files changed, 416 insertions(+), 37 deletions(-)

diff --git a/ui/src/app/core-services/datalake/DatalakeQueryParameterBuilder.ts b/ui/src/app/core-services/datalake/DatalakeQueryParameterBuilder.ts
index 9854137..cb50c23 100644
--- a/ui/src/app/core-services/datalake/DatalakeQueryParameterBuilder.ts
+++ b/ui/src/app/core-services/datalake/DatalakeQueryParameterBuilder.ts
@@ -42,6 +42,12 @@ export class DatalakeQueryParameterBuilder {
     return this;
   }
 
+  public withAggregationFunction(aggregationFunction: string) {
+    this.queryParams.aggregationFunction = aggregationFunction;
+
+    return this;
+  }
+
   public withAggregation(aggregationFunction: string,
                          aggregationTimeUnit: string,
                          aggregationTimeValue: number) {
@@ -71,6 +77,18 @@ export class DatalakeQueryParameterBuilder {
     return this;
   }
 
+  public withLimit(limit: number): DatalakeQueryParameterBuilder {
+    this.queryParams.limit = limit;
+
+    return this;
+  }
+
+  public withOrdering(order: string): DatalakeQueryParameterBuilder {
+    this.queryParams.order = order;
+
+    return this;
+  }
+
   public withOffset(offset: number,
                     limit: number): DatalakeQueryParameterBuilder {
     this.queryParams.offset = offset;
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
index 99ba437..2fd671f 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
+++ b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
@@ -59,6 +59,12 @@
 
                         </sp-data-explorer-line-chart-widget-config>
                     </div>
+                    <div *ngIf="currentlyConfiguredWidget.widgetType === 'indicator-chart'" class="h-100 p-0">
+                        <sp-data-explorer-indicator-chart-widget-config
+                                [currentlyConfiguredWidget]="currentlyConfiguredWidget"
+                                [dataLakeMeasure]="dataLakeMeasure">
+                        </sp-data-explorer-indicator-chart-widget-config>
+                    </div>
                 </div>
                 <div *ngIf="selectedIndex == 2">
                     <sp-data-explorer-widget-appearance-settings
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html
index ebd845f..e738a40 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html
@@ -44,13 +44,16 @@
     <h5>Visualization Type</h5>
     <mat-form-field color="accent" fxFlex="100">
         <mat-label>Select visualization</mat-label>
-        <mat-select [(value)]="currentlyConfiguredWidget.widgetType" (selectionChange)="configureVis($event)">
+        <mat-select [(value)]="currentlyConfiguredWidget.widgetType">
             <mat-option [value]="'line-chart'">
                 <span class="pipeline-name">Line Chart</span>
             </mat-option>
             <mat-option [value]="'table'">
                 <span class="pipeline-name">Table</span>
             </mat-option>
+            <mat-option [value]="'indicator-chart'">
+                <span class="pipeline-name">Indicator</span>
+            </mat-option>
         </mat-select>
     </mat-form-field>
 
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
index a86571d..58c88bf 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
+++ b/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
@@ -81,22 +81,6 @@ export class DataExplorerWidgetDataSettingsComponent implements OnInit {
       this.availableMeasurements.find(m => m.measureName === measureName);
   }
 
-  configureVis(event: MatSelectChange) {
-    if (event.value === 'line-chart') {
-      this.initiateLineChart();
-    } else if (event.value === 'table') {
-      this.initiateTable();
-    }
-  }
-
-  initiateLineChart() {
-
-  }
-
-  initiateTable() {
-
-  }
-
   createWidget() {
     this.createWidgetEmitter.emit({ a: this.dataLakeMeasure, b: this.currentlyConfiguredWidget });
   }
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 7e6a507..5d87a1f 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
@@ -81,6 +81,19 @@
                             [dataLakeMeasure]="dataLakeMeasure"
                             class="h-100"></sp-data-explorer-image-widget>
                 </div>
+                <div *ngIf="configuredWidget.widgetType === 'indicator-chart'" class="h-100 p-0">
+                    <sp-data-explorer-indicator-chart-widget
+                            (removeWidgetCallback)="removeWidget()"
+                            [timeSettings]="timeSettings"
+                            [gridsterItem]="dashboardItem"
+                            [gridsterItemComponent]="gridsterItemComponent"
+                            [editMode]="editMode"
+                            [dataViewDashboardItem]="dashboardItem"
+                            [dataExplorerWidget]="configuredWidget"
+                            [dataLakeMeasure]="dataLakeMeasure"
+                            class="h-100">
+                    </sp-data-explorer-indicator-chart-widget>
+                </div>
             </div>
         </div>
     </div>
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 23544e1..d44b1dd 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
@@ -63,7 +63,6 @@ export abstract class BaseDataExplorerWidget<T extends DataExplorerWidgetModel>
   public showIsLoadingData: boolean;
 
   constructor(protected dataLakeRestService: DatalakeRestService,
-              protected dialog: MatDialog,
               protected widgetConfigurationService: WidgetConfigurationService,
               protected resizeService: ResizeService) {
 
@@ -81,6 +80,12 @@ export abstract class BaseDataExplorerWidget<T extends DataExplorerWidgetModel>
         }
       }
     });
+    this.resizeService.resizeSubject.subscribe(info => {
+      if (info.gridsterItem.id === this.dataExplorerWidget._id) {
+        this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - 40);
+      }
+    });
+    this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - 40);
   }
 
   ngOnDestroy(): void {
@@ -120,5 +125,7 @@ export abstract class BaseDataExplorerWidget<T extends DataExplorerWidgetModel>
 
   public abstract refreshView();
 
+  public abstract onResize(width: number, height: number);
+
 
 }
diff --git a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts
index cec0800..82e06b5 100644
--- a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts
@@ -48,11 +48,10 @@ export class ImageWidgetComponent extends BaseDataExplorerWidget<ImageWidgetMode
   public imagesRoutes = [];
 
   constructor(
-      protected dataLakeRestService: DatalakeRestService,
-      protected dialog: MatDialog,
+      dataLakeRestService: DatalakeRestService,
       widgetConfigurationService: WidgetConfigurationService,
       resizeService: ResizeService) {
-    super(dataLakeRestService, dialog, widgetConfigurationService, resizeService);
+    super(dataLakeRestService, widgetConfigurationService, resizeService);
   }
 
   ngOnInit(): void {
@@ -99,4 +98,7 @@ export class ImageWidgetComponent extends BaseDataExplorerWidget<ImageWidgetMode
   buildQuery(): DatalakeQueryParameters {
     return DatalakeQueryParameterBuilder.create(this.timeSettings.startTime, this.timeSettings.endTime).build();
   }
+
+  onResize(width: number, height: number) {
+  }
 }
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.html b/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.html
new file mode 100644
index 0000000..6e3e173
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.html
@@ -0,0 +1,72 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column">
+    <h5>Indicator Field</h5>
+    <mat-form-field color="accent" fxFlex="100">
+        <mat-label>Select Field</mat-label>
+        <mat-select [(value)]="currentlyConfiguredWidget.dataConfig.selectedProperty" (selectionChange)="setSelectedProperties($event)">
+            <mat-option [value]="property.runtimeName" *ngFor="let property of currentlyConfiguredWidget.dataConfig.availableProperties">
+                <span class="pipeline-name">{{ property.runtimeName }}</span>
+            </mat-option>
+        </mat-select>
+    </mat-form-field>
+
+    <mat-form-field color="accent" fxFlex="100">
+        <mat-label>Value Aggregation</mat-label>
+        <mat-select [(value)]="currentlyConfiguredWidget.dataConfig.numberAggregation" (selectionChange)="triggerDataRefresh()">
+            <mat-option [value]="'MEAN'">
+                <span class="pipeline-name">Mean</span>
+            </mat-option>
+            <mat-option [value]="'FIRST'">
+                <span class="pipeline-name">First</span>
+            </mat-option>
+            <mat-option [value]="'LAST'">
+                <span class="pipeline-name">Last</span>
+            </mat-option>
+            <mat-option [value]="'MIN'">
+                <span class="pipeline-name">Min</span>
+            </mat-option>
+            <mat-option [value]="'MAX'">
+                <span class="pipeline-name">Max</span>
+            </mat-option>
+        </mat-select>
+    </mat-form-field>
+
+    <mat-form-field color="accent" fxFlex="100">
+        <mat-label>Delta Aggregation</mat-label>
+        <mat-select [(value)]="currentlyConfiguredWidget.dataConfig.deltaAggregation" (selectionChange)="triggerDataRefresh()">
+            <mat-option [value]="'MEAN'">
+                <span class="pipeline-name">Mean</span>
+            </mat-option>
+            <mat-option [value]="'FIRST'">
+                <span class="pipeline-name">First</span>
+            </mat-option>
+            <mat-option [value]="'LAST'">
+                <span class="pipeline-name">Last</span>
+            </mat-option>
+            <mat-option [value]="'MIN'">
+                <span class="pipeline-name">Min</span>
+            </mat-option>
+            <mat-option [value]="'MAX'">
+                <span class="pipeline-name">Max</span>
+            </mat-option>
+        </mat-select>
+    </mat-form-field>
+</div>
+
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.scss b/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.scss
new file mode 100644
index 0000000..13cbc4a
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.scss
@@ -0,0 +1,17 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.ts b/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.ts
new file mode 100644
index 0000000..cb76343
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/indicator/config/indicator-chart-widget-config.component.ts
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { BaseWidgetConfig } from '../../base/base-widget-config';
+import { IndicatorChartWidgetModel } from '../model/indicator-chart-widget.model';
+import { EventPropertyUnion } from '../../../../../core-model/gen/streampipes-model';
+
+@Component({
+  selector: 'sp-data-explorer-indicator-chart-widget-config',
+  templateUrl: './indicator-chart-widget-config.component.html',
+  styleUrls: ['./indicator-chart-widget-config.component.scss']
+})
+export class IndicatorWidgetConfigComponent extends BaseWidgetConfig<IndicatorChartWidgetModel> implements OnInit {
+
+  ngOnInit(): void {
+    this.updateWidgetConfigOptions();
+  }
+
+  setSelectedProperties(selectedColumn: EventPropertyUnion) {
+    this.triggerDataRefresh();
+  }
+
+  protected updateWidgetConfigOptions() {
+    if (this.dataLakeMeasure.measureName && !this.currentlyConfiguredWidget.dataConfig.availableProperties) {
+      this.currentlyConfiguredWidget.dataConfig.availableProperties = this.getNumericProperty(this.dataLakeMeasure.eventSchema);
+    }
+  }
+
+}
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.html b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.html
new file mode 100644
index 0000000..202fb78
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.html
@@ -0,0 +1,32 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" fxFlex="100"
+     [ngStyle]="{background: dataExplorerWidget.baseAppearanceConfig.backgroundColor, color: dataExplorerWidget.baseAppearanceConfig.textColor}">
+
+    <sp-load-data-spinner *ngIf="showIsLoadingData" class="h-100"></sp-load-data-spinner>
+    <sp-no-data-in-date-range *ngIf="showNoDataInDateRange" [viewDateRange]="timeSettings"></sp-no-data-in-date-range>
+
+    <plotly-plot *ngIf="data !== undefined && !showNoDataInDateRange && !showIsLoadingData"
+                 [divId]="dataExplorerWidget._id"
+                 class="plotly-container"
+                 [data]="data"
+                 [layout]="graph.layout"
+                 [config]="graph.config">
+    </plotly-plot>
+</div>
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.scss b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.scss
new file mode 100644
index 0000000..13cbc4a
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.scss
@@ -0,0 +1,17 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.ts b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.ts
new file mode 100644
index 0000000..55e976c
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/indicator/indicator-chart-widget.component.ts
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { BaseDataExplorerWidget } from '../base/base-data-explorer-widget';
+import { LineChartWidgetModel } from '../line-chart/model/line-chart-widget.model';
+import { DatalakeRestService } from '../../../../platform-services/apis/datalake-rest.service';
+import { WidgetConfigurationService } from '../../../services/widget-configuration.service';
+import { ResizeService } from '../../../services/resize.service';
+import { DataResult } from '../../../../core-model/datalake/DataResult';
+import { DatalakeQueryParameters } from '../../../../core-services/datalake/DatalakeQueryParameters';
+import { DatalakeQueryParameterBuilder } from '../../../../core-services/datalake/DatalakeQueryParameterBuilder';
+import { Observable, zip } from 'rxjs';
+import { IndicatorChartWidgetModel } from './model/indicator-chart-widget.model';
+
+@Component({
+  selector: 'sp-data-explorer-indicator-chart-widget',
+  templateUrl: './indicator-chart-widget.component.html',
+  styleUrls: ['./indicator-chart-widget.component.scss']
+})
+export class IndicatorChartWidgetComponent extends BaseDataExplorerWidget<IndicatorChartWidgetModel> implements OnInit {
+
+  data = [
+    {
+      type: 'indicator',
+      mode: 'number+delta',
+      value: 400,
+      number: {prefix: ''},
+      delta: {position: 'top', reference: 320},
+      domain: {x: [0, 1], y: [0, 1]}
+    }
+  ];
+
+  graph = {
+    layout: {
+      font: {
+        color: '#FFF'
+      },
+      autosize: true,
+      plot_bgcolor: '#fff',
+      paper_bgcolor: '#fff',
+      margin: {t: 0, b: 0, l: 0, r: 0},
+      grid: {rows: 2, columns: 2, pattern: 'independent'},
+      template: {
+        data: {
+          indicator: [
+            {
+              mode: 'number+delta',
+              delta: {reference: 90}
+            }
+          ]
+        }
+      }
+    },
+
+    config: {
+      modeBarButtonsToRemove: ['lasso2d', 'select2d', 'toggleSpikelines', 'toImage'],
+      displaylogo: false,
+      displayModeBar: false,
+      responsive: true
+    }
+  };
+
+  constructor(dataLakeRestService: DatalakeRestService,
+              widgetConfigurationService: WidgetConfigurationService,
+              resizeService: ResizeService) {
+    super(dataLakeRestService, widgetConfigurationService, resizeService);
+  }
+
+  refreshData() {
+    zip(this.getQuery(this.dataExplorerWidget.dataConfig.numberAggregation),
+        this.getQuery(this.dataExplorerWidget.dataConfig.deltaAggregation))
+        .subscribe(result => {
+      this.prepareData(result[0], result[1]);
+    });
+  }
+
+  getQuery(aggregation: string): Observable<DataResult> {
+    return this.dataLakeRestService.getData(this.dataLakeMeasure.measureName, this.buildQuery(aggregation));
+  }
+
+  refreshView() {
+    this.updateAppearance();
+  }
+
+  prepareData(numberResult: DataResult, deltaResult: DataResult) {
+    this.data[0].value = numberResult.total > 0 ? numberResult.rows[0][1] : '-';
+    this.data[0].delta.reference = numberResult.total > 0 ? deltaResult.rows[0][1] : '-';
+  }
+
+  updateAppearance() {
+    this.graph.layout.paper_bgcolor = this.dataExplorerWidget.baseAppearanceConfig.backgroundColor;
+    this.graph.layout.plot_bgcolor = this.dataExplorerWidget.baseAppearanceConfig.backgroundColor;
+    this.graph.layout.font.color = this.dataExplorerWidget.baseAppearanceConfig.textColor;
+  }
+
+  buildQuery(aggregation: string): DatalakeQueryParameters {
+    return DatalakeQueryParameterBuilder.create(this.timeSettings.startTime, this.timeSettings.endTime)
+        .withColumnFilter([this.dataExplorerWidget.dataConfig.selectedProperty])
+        .withAggregationFunction(aggregation)
+        .build();
+  }
+
+  onResize(width: number, height: number) {
+    this.graph.layout.autosize = false;
+    (this.graph.layout as any).width = width;
+    (this.graph.layout as any).height = height;
+  }
+
+
+}
diff --git a/ui/src/app/data-explorer/components/widgets/indicator/model/indicator-chart-widget.model.ts b/ui/src/app/data-explorer/components/widgets/indicator/model/indicator-chart-widget.model.ts
new file mode 100644
index 0000000..d7eeff0
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/indicator/model/indicator-chart-widget.model.ts
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { DataExplorerWidgetModel, EventPropertyUnion } from '../../../../../core-model/gen/streampipes-model';
+
+export interface IndicatorChartDataConfig {
+  selectedProperty: string;
+  availableProperties: EventPropertyUnion[];
+  numberAggregation: string;
+  deltaAggregation: string;
+}
+
+export interface IndicatorChartWidgetModel extends DataExplorerWidgetModel {
+  dataConfig: IndicatorChartDataConfig;
+}
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 8e10045..f8fa446 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
@@ -55,14 +55,13 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget<LineChartWi
   offsetRightLineChart = 10;
 
 
-  constructor(public dialog: MatDialog,
-              public colorService: ColorService,
+  constructor(public colorService: ColorService,
               public renderer: Renderer2,
-              protected dataLakeRestService: DatalakeRestService,
+              dataLakeRestService: DatalakeRestService,
               public labelService: LabelService,
               widgetConfigurationService: WidgetConfigurationService,
               resizeService: ResizeService) {
-    super(dataLakeRestService, dialog, widgetConfigurationService, resizeService);
+    super(dataLakeRestService, widgetConfigurationService, resizeService);
   }
 
   // indicator variable if labeling mode is activated
@@ -307,8 +306,6 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget<LineChartWi
   }
 
   transformData(data: DataResult, xKey: string): DataResult {
-    console.log(xKey);
-    console.log(data);
     const columnsContainingNumbers = [];
     const columnsContainingStrings = [];
 
@@ -702,4 +699,10 @@ export class LineChartWidgetComponent extends BaseDataExplorerWidget<LineChartWi
             this.dataExplorerWidget.dataConfig.aggregationTimeUnit, this.dataExplorerWidget.dataConfig.aggregationValue)
         .build();
   }
+
+  onResize(width: number, height: number) {
+    this.graph.layout.autosize = false;
+    (this.graph.layout as any).width = width;
+    (this.graph.layout as any).height = height;
+  }
 }
diff --git a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts
index ab31955..a015b31 100644
--- a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts
@@ -40,11 +40,10 @@ export class TableWidgetComponent extends BaseDataExplorerWidget<TableWidgetMode
 
   dataSource = new MatTableDataSource();
 
-  constructor(protected dataLakeRestService: DatalakeRestService,
-              protected dialog: MatDialog,
+  constructor(dataLakeRestService: DatalakeRestService,
               widgetConfigurationService: WidgetConfigurationService,
               resizeService: ResizeService) {
-    super(dataLakeRestService, dialog, widgetConfigurationService, resizeService);
+    super(dataLakeRestService, widgetConfigurationService, resizeService);
   }
 
   ngOnInit(): void {
@@ -119,4 +118,7 @@ export class TableWidgetComponent extends BaseDataExplorerWidget<TableWidgetMode
     return DatalakeQueryParameterBuilder.create(this.timeSettings.startTime, this.timeSettings.endTime).build();
   }
 
+  onResize(width: number, height: number) {
+  }
+
 }
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts b/ui/src/app/data-explorer/data-explorer.module.ts
index 535ab6b..850d270 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -71,8 +71,8 @@ import { WidgetConfigurationService } from './services/widget-configuration.serv
 import { LineChartWidgetConfigComponent } from './components/widgets/line-chart/config/line-chart-widget-config.component';
 import { ImageWidgetConfigComponent } from './components/widgets/image/config/image-widget-config.component';
 import { DatalakeRestService } from '../platform-services/apis/datalake-rest.service';
-
-const dashboardWidgets = [];
+import { IndicatorChartWidgetComponent } from './components/widgets/indicator/indicator-chart-widget.component';
+import { IndicatorWidgetConfigComponent } from './components/widgets/indicator/config/indicator-chart-widget-config.component';
 
 export const MY_NATIVE_FORMATS = {
   fullPickerInput: {
@@ -83,11 +83,11 @@ export const MY_NATIVE_FORMATS = {
     minute: 'numeric',
     hour12: false
   },
-  datePickerInput: { year: 'numeric', month: 'numeric', day: 'numeric', hour12: false },
-  timePickerInput: { hour: 'numeric', minute: 'numeric', hour12: false },
-  monthYearLabel: { year: 'numeric', month: 'short', hour12: false },
-  dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric', hour12: false },
-  monthYearA11yLabel: { year: 'numeric', month: 'long', hour12: false }
+  datePickerInput: {year: 'numeric', month: 'numeric', day: 'numeric', hour12: false},
+  timePickerInput: {hour: 'numeric', minute: 'numeric', hour12: false},
+  monthYearLabel: {year: 'numeric', month: 'short', hour12: false},
+  dateA11yLabel: {year: 'numeric', month: 'long', day: 'numeric', hour12: false},
+  monthYearA11yLabel: {year: 'numeric', month: 'long', hour12: false}
 };
 
 
@@ -130,6 +130,8 @@ export const MY_NATIVE_FORMATS = {
     TableWidgetComponent,
     ImageWidgetComponent,
     ImageWidgetConfigComponent,
+    IndicatorChartWidgetComponent,
+    IndicatorWidgetConfigComponent,
     LineChartWidgetComponent,
     LineChartWidgetConfigComponent,
     TimeRangeSelectorComponent,