Add status widget to data explorer (#3226)
diff --git a/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.html b/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.html
new file mode 100644
index 0000000..518f3fc
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.html
@@ -0,0 +1,158 @@
+<!--
+ ~ 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.
+ ~
+ -->
+
+<sp-visualization-config-outer
+ [configurationValid]="
+ currentlyConfiguredWidget.visualizationConfig.configurationValid
+ "
+>
+ <sp-configuration-box title="Settings">
+ <div fxLayout="column" fxLayoutGap="10px">
+ <div
+ fxLayout="row"
+ fxLayoutGap="10px"
+ fxLayoutAlign="start center"
+ fxFlex="100"
+ >
+ <small fxFlex="30">Select Value Type</small>
+ <mat-radio-group
+ [(ngModel)]="
+ currentlyConfiguredWidget.visualizationConfig
+ .selectedDataType
+ "
+ (change)="selectDataType($event.source.value)"
+ >
+ <mat-radio-button [value]="'number'"
+ >Numeric Value</mat-radio-button
+ >
+ <mat-radio-button [value]="'boolean'"
+ >Boolean Value</mat-radio-button
+ >
+ </mat-radio-group>
+ </div>
+
+ <div
+ *ngIf="
+ currentlyConfiguredWidget.visualizationConfig
+ .selectedDataType === 'number'
+ "
+ fxLayout="column"
+ fxLayoutGap="10px"
+ >
+ <div
+ fxLayout="row"
+ fxLayoutGap="10px"
+ fxLayoutAlign="start center"
+ fxFlex="100"
+ >
+ <small
+ fxFlex="30"
+ matTooltip="Interval in seconds in which an event must arrive"
+ matTooltipPosition="above"
+ >Interval [sec]</small
+ >
+ <mat-form-field color="accent" appearance="outline" fxFlex>
+ <input
+ type="number"
+ [(ngModel)]="
+ currentlyConfiguredWidget.visualizationConfig
+ .selectedInterval
+ "
+ matInput
+ (input)="selectInterval($event.target.value)"
+ min="0"
+ />
+ </mat-form-field>
+ </div>
+ <div
+ fxLayout="row"
+ fxLayoutGap="10px"
+ fxLayoutAlign="start center"
+ fxFlex="100"
+ >
+ <small>Show Last Seen Timestamp</small>
+ <mat-checkbox
+ color="accent"
+ [(ngModel)]="
+ currentlyConfiguredWidget.visualizationConfig
+ .selectedLastSeen
+ "
+ (ngModelChange)="showLastSeen($event)"
+ >
+ </mat-checkbox>
+ </div>
+ </div>
+
+ <div
+ *ngIf="
+ currentlyConfiguredWidget.visualizationConfig
+ .selectedDataType === 'boolean'
+ "
+ fxLayout="column"
+ fxLayoutGap="10px"
+ >
+ <div
+ fxLayout="row"
+ fxLayoutGap="10px"
+ fxLayoutAlign="start center"
+ fxFlex="100"
+ >
+ <small fxFlex="30">Field</small>
+ <sp-select-property
+ [availableProperties]="fieldProvider.booleanFields"
+ [selectedProperty]="
+ currentlyConfiguredWidget.visualizationConfig
+ .selectedBooleanFieldToObserve
+ "
+ (changeSelectedProperty)="
+ selectBooleanFieldToObserve($event)
+ "
+ fxFlex
+ ></sp-select-property>
+ </div>
+
+ <div
+ fxLayout="row"
+ fxLayoutGap="10px"
+ fxLayoutAlign="start center"
+ fxFlex="100"
+ >
+ <small fxFlex="30">Select Mapping</small>
+ <mat-radio-group
+ [(ngModel)]="
+ currentlyConfiguredWidget.visualizationConfig
+ .selectedMappingGreenTrue
+ "
+ (change)="selectMappingGreenTrue($event.source.value)"
+ >
+ <mat-radio-button [value]="true">
+ <span class="color-box green-box"></span> True
+ <span class="spacing"></span>
+ <span class="color-box red-box"></span> False
+ </mat-radio-button>
+ <mat-radio-button [value]="false">
+ <span class="color-box red-box"></span> True
+ <span class="spacing"></span>
+ <span class="color-box green-box"></span> False
+ </mat-radio-button>
+ </mat-radio-group>
+ </div>
+ </div>
+ </div>
+ </sp-configuration-box>
+</sp-visualization-config-outer>
diff --git a/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.scss b/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.scss
new file mode 100644
index 0000000..c3105ba
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.scss
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+.color-box {
+ display: inline-block;
+ width: 12px;
+ height: 12px;
+ margin-right: 5px;
+ border-radius: 50%;
+}
+.spacing {
+ margin-left: 15px;
+}
+.green-box {
+ background-color: green;
+}
+
+.red-box {
+ background-color: red;
+}
+
+.checkbox-container {
+ margin-top: 20px;
+}
diff --git a/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.ts b/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.ts
new file mode 100644
index 0000000..f671616
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/status/config/status-widget-config.component.ts
@@ -0,0 +1,91 @@
+/*
+ * 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 } from '@angular/core';
+import { BaseWidgetConfig } from '../../base/base-widget-config';
+import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
+import {
+ StatusWidgetModel,
+ StatusVisConfig,
+} from '../model/status-widget.model';
+import { DataExplorerFieldProviderService } from '../../../../services/data-explorer-field-provider-service';
+import { DataExplorerField } from '@streampipes/platform-services';
+
+@Component({
+ selector: 'sp-data-explorer-status-widget-config',
+ templateUrl: './status-widget-config.component.html',
+ styleUrls: ['./status-widget-config.component.scss'],
+})
+export class StatusWidgetConfigComponent extends BaseWidgetConfig<
+ StatusWidgetModel,
+ StatusVisConfig
+> {
+ constructor(
+ widgetConfigurationService: WidgetConfigurationService,
+ fieldService: DataExplorerFieldProviderService,
+ ) {
+ super(widgetConfigurationService, fieldService);
+ }
+
+ selectDataType(selectedDataType: string): void {
+ this.currentlyConfiguredWidget.visualizationConfig.selectedDataType =
+ selectedDataType;
+ this.triggerViewRefresh();
+ }
+
+ selectInterval(selectedInterval: number): void {
+ this.currentlyConfiguredWidget.visualizationConfig.selectedInterval =
+ selectedInterval;
+ this.triggerViewRefresh();
+ }
+
+ showLastSeen(selectedLastSeen: boolean): void {
+ this.currentlyConfiguredWidget.visualizationConfig.showLastSeen =
+ selectedLastSeen;
+ this.triggerViewRefresh();
+ }
+
+ selectBooleanFieldToObserve(
+ selectedBooleanFieldToObserve: DataExplorerField,
+ ): void {
+ this.currentlyConfiguredWidget.visualizationConfig.selectedBooleanFieldToObserve =
+ selectedBooleanFieldToObserve;
+ this.triggerViewRefresh();
+ }
+
+ selectMappingGreenTrue(selectedMappingGreenTrue: boolean): void {
+ this.currentlyConfiguredWidget.visualizationConfig.selectedMappingGreenTrue =
+ selectedMappingGreenTrue;
+ this.triggerViewRefresh();
+ }
+
+ protected applyWidgetConfig(config: StatusVisConfig): void {
+ config.selectedBooleanFieldToObserve =
+ this.fieldService.getSelectedField(
+ config.selectedBooleanFieldToObserve,
+ this.fieldProvider.allFields,
+ () => this.fieldProvider.allFields[0],
+ );
+ this.currentlyConfiguredWidget.visualizationConfig.selectedInterval ??= 5;
+ this.currentlyConfiguredWidget.visualizationConfig.selectedMappingGreenTrue ??=
+ true;
+ }
+ protected requiredFieldsForChartPresent(): boolean {
+ return true;
+ }
+}
diff --git a/ui/src/app/data-explorer/components/widgets/status/model/status-widget.model.ts b/ui/src/app/data-explorer/components/widgets/status/model/status-widget.model.ts
new file mode 100644
index 0000000..73bb53e
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/status/model/status-widget.model.ts
@@ -0,0 +1,37 @@
+/*
+ * 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 {
+ DataExplorerDataConfig,
+ DataExplorerWidgetModel,
+ DataExplorerField,
+} from '@streampipes/platform-services';
+import { DataExplorerVisConfig } from '../../../../models/dataview-dashboard.model';
+
+export interface StatusVisConfig extends DataExplorerVisConfig {
+ selectedDataType: string;
+ selectedInterval: number;
+ showLastSeen: boolean;
+ selectedBooleanFieldToObserve: DataExplorerField;
+ selectedMappingGreenTrue: boolean;
+}
+
+export interface StatusWidgetModel extends DataExplorerWidgetModel {
+ dataConfig: DataExplorerDataConfig;
+ visualizationConfig: StatusVisConfig;
+}
diff --git a/ui/src/app/data-explorer/components/widgets/status/status-widget.component.html b/ui/src/app/data-explorer/components/widgets/status/status-widget.component.html
new file mode 100644
index 0000000..ad01626
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/status/status-widget.component.html
@@ -0,0 +1,60 @@
+<!--
+ ~ 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"
+ fxLayoutAlign="center center"
+ fxLayout="column"
+ class="main-panel"
+ [ngStyle]="{
+ background: dataExplorerWidget.baseAppearanceConfig.backgroundColor,
+ color: dataExplorerWidget.baseAppearanceConfig.textColor,
+ overflowX: 'auto'
+ }"
+>
+ <sp-no-data-in-date-range
+ *ngIf="showNoDataInDateRange"
+ [viewDateRange]="timeSettings"
+ class="h-50"
+ >
+ </sp-no-data-in-date-range>
+
+ <div fxLayoutAlign="center center">
+ <div
+ class="tl-container"
+ [ngStyle]="{
+ width: containerWidth + 'px',
+ height: containerHeight + 'px'
+ }"
+ >
+ <div
+ class="light"
+ [ngClass]="{
+ 'light-red': !active,
+ 'light-green': active
+ }"
+ [ngStyle]="{
+ width: lightWidth + 'px',
+ height: lightHeight + 'px'
+ }"
+ ></div>
+ </div>
+ </div>
+ <div *ngIf="selectedDataType === 'number' && showLastSeen">
+ <h5>Last seen: {{ lastTimestamp | date: 'short' }}</h5>
+ </div>
+</div>
diff --git a/ui/src/app/data-explorer/components/widgets/status/status-widget.component.scss b/ui/src/app/data-explorer/components/widgets/status/status-widget.component.scss
new file mode 100644
index 0000000..ac65666
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/status/status-widget.component.scss
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+.h-100 {
+ height: 100%;
+}
+
+.tl-container {
+ background-color: #222;
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ padding: 20px;
+ border-radius: 10px;
+}
+
+.light {
+ border-radius: 50%;
+ background-color: #3d3535;
+ background: repeating-linear-gradient(#333, #443 5px);
+}
+
+.light-red,
+.light-green {
+ box-shadow: 0 0 40px;
+ z-index: 1;
+}
+
+.light-red {
+ background: repeating-linear-gradient(#f00, #e00 5px);
+ box-shadow: 0 0 40px #f00;
+}
+
+.light-green {
+ background: repeating-linear-gradient(#0d0, #0c0 5px);
+ box-shadow: 0 0 40px #0d0;
+}
+
+.title-panel {
+ font-size: 20px;
+ height: 30px;
+ margin: 10px 0;
+}
diff --git a/ui/src/app/data-explorer/components/widgets/status/status-widget.component.ts b/ui/src/app/data-explorer/components/widgets/status/status-widget.component.ts
new file mode 100644
index 0000000..abb41e5
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widgets/status/status-widget.component.ts
@@ -0,0 +1,164 @@
+/*
+ * 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 { BaseDataExplorerWidgetDirective } from '../base/base-data-explorer-widget.directive';
+import { StatusWidgetModel } from './model/status-widget.model';
+import {
+ DataExplorerField,
+ SpQueryResult,
+} from '@streampipes/platform-services';
+
+@Component({
+ selector: 'sp-data-explorer-status-widget',
+ templateUrl: './status-widget.component.html',
+ styleUrls: ['./status-widget.component.scss'],
+})
+export class StatusWidgetComponent
+ extends BaseDataExplorerWidgetDirective<StatusWidgetModel>
+ implements OnInit
+{
+ width: number;
+ height: number;
+
+ row: any[][];
+ header: string[];
+ fieldIndex = -1;
+
+ containerWidth: number;
+ containerHeight: number;
+
+ lightWidth: number;
+ lightHeight: number;
+
+ selectedDataType: string;
+ selectedInterval: number;
+ showLastSeen: boolean;
+ selectedBooleanFieldToObserve: DataExplorerField;
+ selectedMappingGreenTrue: boolean;
+
+ lastTimestamp = 0;
+ active: boolean;
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ this.onResize(
+ this.gridsterItemComponent.width - this.widthOffset,
+ this.gridsterItemComponent.height - this.heightOffset,
+ );
+ this.updateSettings();
+ }
+
+ updateSettings(): void {
+ this.selectedDataType =
+ this.dataExplorerWidget.visualizationConfig.selectedDataType;
+ this.selectedInterval =
+ this.dataExplorerWidget.visualizationConfig.selectedInterval;
+ this.showLastSeen =
+ this.dataExplorerWidget.visualizationConfig.showLastSeen;
+ this.selectedBooleanFieldToObserve =
+ this.dataExplorerWidget.visualizationConfig.selectedBooleanFieldToObserve;
+ this.selectedMappingGreenTrue =
+ this.dataExplorerWidget.visualizationConfig.selectedMappingGreenTrue;
+ }
+
+ getNumericalStatus(): void {
+ const timestamp = new Date().getTime();
+ this.active =
+ this.lastTimestamp >= timestamp - this.selectedInterval * 1000;
+ }
+
+ getBooleanStatus(): void {
+ if (this.selectedMappingGreenTrue) {
+ this.active = this.row[0][this.fieldIndex];
+ } else {
+ this.active = !this.row[0][this.fieldIndex];
+ }
+ }
+
+ booleanFieldToObserve(): void {
+ this.fieldIndex = this.header.indexOf(
+ this.selectedBooleanFieldToObserve.runtimeName,
+ );
+ }
+
+ refreshView(): void {
+ this.updateSettings();
+ if (this.row !== undefined && this.row.length > 0) {
+ if (this.selectedDataType == 'boolean') {
+ this.getBooleanStatus();
+ } else {
+ this.getNumericalStatus();
+ }
+ }
+ }
+
+ beforeDataFetched(): void {
+ this.setShownComponents(false, false, true, false);
+ }
+
+ onDataReceived(spQueryResult: SpQueryResult[]): void {
+ if (
+ spQueryResult.length > 0 &&
+ spQueryResult[0].allDataSeries.length > 0
+ ) {
+ this.header = spQueryResult[0].allDataSeries[0].headers;
+ this.row = spQueryResult[0].allDataSeries[0].rows;
+ this.lastTimestamp = spQueryResult[0].allDataSeries[0].rows[0][0];
+
+ if (this.selectedDataType == 'number') {
+ this.getNumericalStatus();
+ } else if (this.selectedDataType == 'boolean') {
+ this.booleanFieldToObserve();
+ this.getBooleanStatus();
+ }
+ this.setShownComponents(false, true, false, false);
+ } else {
+ this.setShownComponents(true, false, false, false);
+ }
+ }
+
+ onResize(width: number, heigth: number): void {
+ this.containerHeight = heigth * 0.3;
+ this.containerWidth = this.containerHeight;
+ this.lightWidth = this.containerHeight;
+ this.lightHeight = this.lightWidth;
+ }
+
+ handleUpdatedFields(
+ addedFields: DataExplorerField[],
+ removedFields: DataExplorerField[],
+ ) {
+ const updatedFields = this.fieldUpdateService.updateFieldSelection(
+ [
+ this.dataExplorerWidget.visualizationConfig
+ .selectedBooleanFieldToObserve,
+ ],
+ {
+ addedFields,
+ removedFields,
+ fieldProvider: this.fieldProvider,
+ },
+ () => true,
+ );
+
+ this.selectedBooleanFieldToObserve = updatedFields[0];
+ this.booleanFieldToObserve();
+ this.refreshView();
+ }
+}
diff --git a/ui/src/app/data-explorer/components/widgets/traffic-light/traffic-light-widget.component.ts b/ui/src/app/data-explorer/components/widgets/traffic-light/traffic-light-widget.component.ts
index 80e3490..99df13f 100644
--- a/ui/src/app/data-explorer/components/widgets/traffic-light/traffic-light-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/traffic-light/traffic-light-widget.component.ts
@@ -110,8 +110,6 @@
(this.selectedWarningRange / 100)
);
} else {
- console.log(value);
-
return (
value <=
this.selectedThreshold +
@@ -125,13 +123,13 @@
return !this.exceedsThreshold(value) && !this.isInWarningRange(value);
}
- public refreshView(): void {
+ refreshView(): void {
this.updateSettings();
this.fieldToObserve();
this.getTrafficLightColor();
}
- public beforeDataFetched(): void {
+ beforeDataFetched(): void {
this.setShownComponents(false, false, true, false);
}
@@ -141,12 +139,19 @@
);
}
- public onDataReceived(spQueryResult: SpQueryResult[]): void {
- this.header = spQueryResult[0].allDataSeries[0].headers;
- this.row = spQueryResult[0].allDataSeries[0].rows;
- this.fieldToObserve();
- this.getTrafficLightColor();
- this.setShownComponents(false, true, false, false);
+ onDataReceived(spQueryResult: SpQueryResult[]): void {
+ if (
+ spQueryResult.length > 0 &&
+ spQueryResult[0].allDataSeries.length > 0
+ ) {
+ this.header = spQueryResult[0].allDataSeries[0].headers;
+ this.row = spQueryResult[0].allDataSeries[0].rows;
+ this.fieldToObserve();
+ this.getTrafficLightColor();
+ this.setShownComponents(false, true, false, false);
+ } else {
+ this.setShownComponents(true, false, false, false);
+ }
}
onResize(width: number, heigth: number) {
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts b/ui/src/app/data-explorer/data-explorer.module.ts
index 09b8f33..c3070b4 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -48,6 +48,8 @@
import { ImageWidgetComponent } from './components/widgets/image/image-widget.component';
import { TrafficLightWidgetComponent } from './components/widgets/traffic-light/traffic-light-widget.component';
import { TrafficLightWidgetConfigComponent } from './components/widgets/traffic-light/config/traffic-light-widget-config.component';
+import { StatusWidgetComponent } from './components/widgets/status/status-widget.component';
+import { StatusWidgetConfigComponent } from './components/widgets/status/config/status-widget-config.component';
import { TableWidgetComponent } from './components/widgets/table/table-widget.component';
import { AggregateConfigurationComponent } from './components/widgets/utils/aggregate-configuration/aggregate-configuration.component';
import { LoadDataSpinnerComponent } from './components/widgets/utils/load-data-spinner/load-data-spinner.component';
@@ -251,6 +253,8 @@
TableWidgetConfigComponent,
TrafficLightWidgetComponent,
TrafficLightWidgetConfigComponent,
+ StatusWidgetComponent,
+ StatusWidgetConfigComponent,
MapWidgetConfigComponent,
MapWidgetComponent,
HeatmapWidgetConfigComponent,
diff --git a/ui/src/app/data-explorer/registry/data-explorer-widget-registry.ts b/ui/src/app/data-explorer/registry/data-explorer-widget-registry.ts
index c2d486b..efb221b 100644
--- a/ui/src/app/data-explorer/registry/data-explorer-widget-registry.ts
+++ b/ui/src/app/data-explorer/registry/data-explorer-widget-registry.ts
@@ -54,6 +54,8 @@
import { GaugeWidgetModel } from '../components/widgets/gauge/model/gauge-widget.model';
import { TrafficLightWidgetConfigComponent } from '../components/widgets/traffic-light/config/traffic-light-widget-config.component';
import { TrafficLightWidgetComponent } from '../components/widgets/traffic-light/traffic-light-widget.component';
+import { StatusWidgetConfigComponent } from '../components/widgets/status/config/status-widget-config.component';
+import { StatusWidgetComponent } from '../components/widgets/status/status-widget.component';
@Injectable({ providedIn: 'root' })
export class DataExplorerWidgetRegistry {
@@ -93,6 +95,12 @@
widgetComponent: TrafficLightWidgetComponent,
},
{
+ id: 'status',
+ label: 'Status',
+ widgetConfigurationComponent: StatusWidgetConfigComponent,
+ widgetComponent: StatusWidgetComponent,
+ },
+ {
id: 'map',
label: 'Map',
widgetConfigurationComponent: MapWidgetConfigComponent,