You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ze...@apache.org on 2020/02/20 11:33:18 UTC
[incubator-streampipes] 02/02: Copied dashboard as template for new
data explorer
This is an automated email from the ASF dual-hosted git repository.
zehnder pushed a commit to branch STREAMPIPES-79
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
commit 4862b73650982481c0fb47e5145f288344566c12
Author: Philipp Zehnder <ze...@fzi.de>
AuthorDate: Thu Feb 20 12:32:31 2020 +0100
Copied dashboard as template for new data explorer
---
ui/deployment/dev/config.yml | 3 +-
ui/deployment/modules.yml | 15 ++
.../components/grid/dashboard-grid.component.css | 25 +++
.../components/grid/dashboard-grid.component.html | 32 ++++
.../components/grid/dashboard-grid.component.ts | 98 ++++++++++++
.../overview/dashboard-overview.component.css | 25 +++
.../overview/dashboard-overview.component.html | 98 ++++++++++++
.../overview/dashboard-overview.component.ts | 89 +++++++++++
.../components/panel/dashboard-panel.component.css | 25 +++
.../panel/dashboard-panel.component.html | 35 +++++
.../components/panel/dashboard-panel.component.ts | 128 ++++++++++++++++
.../widget/dashboard-widget.component.css | 53 +++++++
.../widget/dashboard-widget.component.html | 65 ++++++++
.../widget/dashboard-widget.component.ts | 81 ++++++++++
.../components/widgets/area/area-config.ts | 32 ++++
.../widgets/area/area-widget.component.css | 24 +++
.../widgets/area/area-widget.component.html | 41 +++++
.../widgets/area/area-widget.component.ts | 43 ++++++
.../components/widgets/base/base-config.ts | 24 +++
.../widgets/base/base-ngx-charts-widget.ts | 74 +++++++++
.../widgets/base/base-ngx-line-charts-widget.ts | 74 +++++++++
.../widgets/base/base-ngx-line-config.ts | 47 ++++++
.../components/widgets/base/base-widget.ts | 96 ++++++++++++
.../components/widgets/gauge/gauge-config.ts | 48 ++++++
.../widgets/gauge/gauge-widget.component.css | 32 ++++
.../widgets/gauge/gauge-widget.component.html | 36 +++++
.../widgets/gauge/gauge-widget.component.ts | 67 ++++++++
.../components/widgets/image/image-config.ts | 44 ++++++
.../widgets/image/image-widget.component.css | 31 ++++
.../widgets/image/image-widget.component.html | 26 ++++
.../widgets/image/image-widget.component.ts | 62 ++++++++
.../components/widgets/line/line-config.ts | 30 ++++
.../widgets/line/line-widget.component.css | 32 ++++
.../widgets/line/line-widget.component.html | 41 +++++
.../widgets/line/line-widget.component.ts | 46 ++++++
.../components/widgets/number/number-config.ts | 42 +++++
.../widgets/number/number-widget.component.css | 36 +++++
.../widgets/number/number-widget.component.html | 27 ++++
.../widgets/number/number-widget.component.ts | 60 ++++++++
.../components/widgets/table/table-config.ts | 44 ++++++
.../widgets/table/table-widget.component.css | 26 ++++
.../widgets/table/table-widget.component.html | 36 +++++
.../widgets/table/table-widget.component.ts | 77 ++++++++++
.../data-explorer-v2.component.css | 21 +++
.../data-explorer-v2.component.html | 51 +++++++
.../data-explorer-v2/data-explorer-v2.component.ts | 83 ++++++++++
.../data-explorer-v2/data-explorer-v2.module.ts | 126 +++++++++++++++
.../add-visualization-dialog.component.css | 55 +++++++
.../add-visualization-dialog.component.html | 95 ++++++++++++
.../add-visualization-dialog.component.ts | 169 +++++++++++++++++++++
.../edit-dashboard-dialog.component.css | 55 +++++++
.../edit-dashboard-dialog.component.html | 55 +++++++
.../edit-dashboard-dialog.component.ts | 60 ++++++++
.../app/data-explorer-v2/models/dashboard.model.ts | 36 +++++
.../data-explorer-v2/models/gridster-info.model.ts | 24 +++
.../data-explorer-v2/models/multi-series.model.ts | 29 ++++
.../registry/widget-config-builder.ts | 121 +++++++++++++++
.../data-explorer-v2/registry/widget-registry.ts | 44 ++++++
.../sdk/collected-schema-requirements.ts | 38 +++++
ui/src/app/data-explorer-v2/sdk/ep-requirements.ts | 68 +++++++++
.../sdk/extractor/static-property-extractor.ts | 78 ++++++++++
.../sdk/matching/datatype-match.ts | 44 ++++++
.../sdk/matching/domain-property-match.ts | 28 ++++
.../sdk/matching/mapping-property-generator.ts | 46 ++++++
.../sdk/matching/primitive-property-match.ts | 33 ++++
.../sdk/matching/property-match.ts | 32 ++++
ui/src/app/data-explorer-v2/sdk/model/datatypes.ts | 40 +++++
.../app/data-explorer-v2/sdk/model/vocabulary.ts | 23 +++
.../sdk/schema-requirements-builder.ts | 69 +++++++++
.../data-explorer-v2/services/dashboard.service.ts | 137 +++++++++++++++++
.../services/refresh-dashboard.service.ts | 30 ++++
.../data-explorer-v2/services/resize.service.ts | 31 ++++
.../data-explorer-v2/services/websocket.config.ts | 36 +++++
.../services/websocket.settings.ts | 32 ++++
74 files changed, 3858 insertions(+), 1 deletion(-)
diff --git a/ui/deployment/dev/config.yml b/ui/deployment/dev/config.yml
index 0424e05..789ce73 100644
--- a/ui/deployment/dev/config.yml
+++ b/ui/deployment/dev/config.yml
@@ -27,4 +27,5 @@ modules:
- spMyElements
- spDataExplorer
- spConfiguration
- - spDashboard2
\ No newline at end of file
+ - spDashboard2
+ - spDataExplorer2
diff --git a/ui/deployment/modules.yml b/ui/deployment/modules.yml
index 62432db..1285959 100644
--- a/ui/deployment/modules.yml
+++ b/ui/deployment/modules.yml
@@ -169,4 +169,19 @@ spDashboard2:
description: 'dashboard-v2'
icon: 'navigation:ic_apps_24px'
homeImage: '/assets/img/home/configuration.png'
+ admin: false
+spDataExplorer2:
+ ng5: True
+ ng1_templateUrl: ''
+ ng1_controller: ''
+ ng5_moduleName: 'DataExplorerV2Module'
+ ng5_component: 'DataExplorerV2Component'
+ ng5_componentPath: '../data-explorer-v2/data-explorer-v2.component'
+ path: './data-explorer-v2/data-explorer-v2.module'
+ link: 'streampipes.dataexplorerv2'
+ url: '/dataexplorerv2'
+ title: 'Data Explorer'
+ description: 'data-explorer-v2'
+ icon: 'navigation:ic_apps_24px'
+ homeImage: '/assets/img/home/configuration.png'
admin: false
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.css b/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.css
new file mode 100644
index 0000000..6368cea
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.css
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ *
+ */
+
+gridster ::ng-deep {
+ background: white;
+}
+
+gridster.edit ::ng-deep {
+ background: #d3d3d3;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.html b/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.html
new file mode 100644
index 0000000..62c4cc5
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.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 *ngIf="dashboard.displayHeader" class="text-center">
+ <h2>{{dashboard.name}}</h2>
+ <h3>{{dashboard.description}}</h3>
+</div>
+<gridster [options]="options" [ngClass]="editMode ? 'edit' : ''">
+ <ng-container *ngFor="let item of dashboard.widgets;let i=index">
+ <gridster-item [item]="item" #gridsterItemComponent>
+ <dashboard-widget (updateCallback)="propagateItemUpdate($event)"
+ (deleteCallback)="propagateItemRemoval($event)"
+ [item]="item" [widget]="item"
+ [editMode]="editMode" [gridsterItemComponent]="gridsterItemComponent"></dashboard-widget>
+ </gridster-item>
+ </ng-container>
+</gridster>
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.ts b/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.ts
new file mode 100644
index 0000000..fc17584
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/grid/dashboard-grid.component.ts
@@ -0,0 +1,98 @@
+/*
+ * 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 {
+ AfterViewInit,
+ Component, EventEmitter,
+ Input,
+ OnChanges,
+ OnInit, Output,
+ QueryList,
+ SimpleChanges,
+ ViewChildren
+} from "@angular/core";
+import {Dashboard, DashboardConfig, DashboardItem} from "../../models/dashboard.model";
+import {GridsterInfo} from "../../models/gridster-info.model";
+import {ResizeService} from "../../services/resize.service";
+import {GridsterItemComponent, GridType} from "angular-gridster2";
+import {DashboardService} from "../../services/dashboard.service";
+import {RefreshDashboardService} from "../../services/refresh-dashboard.service";
+import {DashboardWidget} from "../../../core-model/dashboard/DashboardWidget";
+
+@Component({
+ selector: 'dashboard-grid',
+ templateUrl: './dashboard-grid.component.html',
+ styleUrls: ['./dashboard-grid.component.css']
+})
+export class DashboardGridComponent implements OnInit, OnChanges {
+
+ @Input() editMode: boolean;
+ @Input() dashboard: Dashboard;
+
+ @Output() deleteCallback: EventEmitter<DashboardItem> = new EventEmitter<DashboardItem>();
+ @Output() updateCallback: EventEmitter<DashboardWidget> = new EventEmitter<DashboardWidget>();
+
+ options: DashboardConfig;
+ loaded: boolean = false;
+
+ @ViewChildren(GridsterItemComponent) gridsterItemComponents: QueryList<GridsterItemComponent>;
+
+ constructor(private resizeService: ResizeService,
+ private dashboardService: DashboardService,
+ private refreshDashboardService: RefreshDashboardService) {
+
+ }
+
+ ngOnInit(): void {
+ this.options = {
+ disablePushOnDrag: true,
+ draggable: { enabled: this.editMode },
+ gridType: GridType.VerticalFixed,
+ minCols: 8,
+ maxCols: 8,
+ minRows: 4,
+ fixedRowHeight: 100,
+ fixedColWidth: 100,
+ resizable: { enabled: this.editMode },
+ itemResizeCallback: ((item, itemComponent) => {
+ this.resizeService.notify({gridsterItem: item, gridsterItemComponent: itemComponent} as GridsterInfo);
+ }),
+ itemInitCallback: ((item, itemComponent) => {
+ this.resizeService.notify({gridsterItem: item, gridsterItemComponent: itemComponent} as GridsterInfo);
+ })
+ };
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes["editMode"] && this.options) {
+ this.options.draggable.enabled = this.editMode;
+ this.options.resizable.enabled = this.editMode;
+ this.options.displayGrid = this.editMode ? 'always' : 'none';
+ this.options.api.optionsChanged();
+ }
+ }
+
+ propagateItemRemoval(widget: DashboardItem) {
+ this.deleteCallback.emit(widget);
+ }
+
+ propagateItemUpdate(dashboardWidget: DashboardWidget) {
+ this.updateCallback.emit(dashboardWidget);
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.css b/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.css
new file mode 100644
index 0000000..dc9cc49
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.css
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ *
+ */
+
+table {
+ width:100%;
+}
+
+.m-20 {
+ margin: 20px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.html b/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.html
new file mode 100644
index 0000000..86a80f4
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.html
@@ -0,0 +1,98 @@
+<!--
+ ~ 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" class="m-20">
+ <div fxLayout="row wrap">
+ <button mat-button mat-raised-button color="primary" (click)="openNewDashboardDialog()">
+ New dashboard
+ </button>
+ </div>
+ <div fxFlex="100" fxLayout="row wrap" fxLayoutAlign="start stretch">
+ <div fxFlex="100" class="assemblyOptions sp-blue-bg" style="padding:5px;">
+ <div fxLayout="row" fxLayoutAlign="start center" fxFlex="100">
+ <h4>My dashboards</h4>
+ <span flex></span>
+ </div>
+ </div>
+ <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="sp-blue-border">
+
+ <table fxFlex="95" mat-table [dataSource]="dataSource" multiTemplateDataRows>
+
+ <ng-container matColumnDef="name">
+ <th fxFlex="60" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Dashboard</th>
+ <td fxFlex="60" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+ {{element.name}}<br/>
+ {{element.description}}
+ </td>
+ </ng-container>
+
+ <ng-container matColumnDef="open">
+ <th fxFlex="10" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Show</th>
+ <td fxFlex="10" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+ <div fxLayout="row">
+ <button mat-button mat-icon-button color="primary"
+ (click)="showDashboard(element)">
+ <i class="material-icons">visibility</i>
+ </button>
+ </div>
+ </td>
+ </ng-container>
+
+ <ng-container matColumnDef="openWindow">
+ <th fxFlex="10" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Window</th>
+ <td fxFlex="10" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+ <div fxLayout="row">
+ <button mat-button mat-icon-button color="primary"
+ (click)="openExternalDashboard(element)">
+ <i class="material-icons">open_in_new</i>
+ </button>
+ </div>
+ </td>
+ </ng-container>
+
+ <ng-container matColumnDef="edit">
+ <th fxFlex="10" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Edit</th>
+ <td fxFlex="10" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+ <div fxLayout="row">
+ <button mat-button mat-icon-button color="primary"
+ (click)="openEditDashboardDialog(element)">
+ <i class="material-icons">edit</i>
+ </button>
+ </div>
+ </td>
+ </ng-container>
+
+ <ng-container matColumnDef="delete">
+ <th fxFlex="10" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Delete</th>
+ <td fxFlex="10" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+ <div fxLayout="row">
+ <button mat-button mat-icon-button color="primary"
+ (click)="openDeleteDashboardDialog(element)">
+ <i class="material-icons">delete</i>
+ </button>
+ </div>
+ </td>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+ <tr mat-row *matRowDef="let element; columns: displayedColumns;">
+ </tr>
+ </table>
+ </div>
+ </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.ts b/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.ts
new file mode 100644
index 0000000..e18af21
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/overview/dashboard-overview.component.ts
@@ -0,0 +1,89 @@
+/*
+ * 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, EventEmitter, Input, OnInit, Output} from "@angular/core";
+import {Dashboard} from "../../models/dashboard.model";
+import {MatTableDataSource} from "@angular/material/table";
+import {MatDialog} from "@angular/material/dialog";
+import {DashboardService} from "../../services/dashboard.service";
+import {AddVisualizationDialogComponent} from "../../dialogs/add-widget/add-visualization-dialog.component";
+import {EditDashboardDialogComponent} from "../../dialogs/edit-dashboard/edit-dashboard-dialog.component";
+
+@Component({
+ selector: 'dashboard-overview',
+ templateUrl: './dashboard-overview.component.html',
+ styleUrls: ['./dashboard-overview.component.css']
+})
+export class DashboardOverviewComponent implements OnInit {
+
+ @Input() dashboards: Array<Dashboard>;
+ @Output() reloadDashboardsEmitter = new EventEmitter<void>();
+ @Output() selectDashboardEmitter = new EventEmitter<Dashboard>();
+
+ dataSource = new MatTableDataSource<Dashboard>();
+ displayedColumns: string[] = ['name', 'open', 'openWindow', 'edit', 'delete'];
+
+ constructor(private dashboardService: DashboardService,
+ public dialog: MatDialog) {
+
+ }
+
+ ngOnInit(): void {
+ this.dataSource.data = this.dashboards;
+ }
+
+ openNewDashboardDialog() {
+ let dashboard = {} as Dashboard;
+ dashboard.widgets = [];
+
+ this.openDashboardModificationDialog(true, dashboard);
+ }
+
+ openDashboardModificationDialog(createMode: boolean, dashboard: Dashboard) {
+ const dialogRef = this.dialog.open(EditDashboardDialogComponent, {
+ width: '70%',
+ panelClass: 'custom-dialog-container'
+ });
+ dialogRef.componentInstance.createMode = createMode;
+ dialogRef.componentInstance.dashboard = dashboard;
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.reloadDashboardsEmitter.emit();
+ });
+ }
+
+ openEditDashboardDialog(dashboard: Dashboard) {
+ this.openDashboardModificationDialog(false, dashboard);
+ }
+
+ openDeleteDashboardDialog(dashboard: Dashboard) {
+ // TODO add confirm dialog
+ this.dashboardService.deleteDashboard(dashboard).subscribe(result => {
+ this.reloadDashboardsEmitter.emit();
+ });
+ }
+
+ showDashboard(dashboard: Dashboard) {
+ this.selectDashboardEmitter.emit(dashboard);
+ }
+
+ openExternalDashboard(dashboard: Dashboard) {
+
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.css b/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.css
new file mode 100644
index 0000000..1faa4d1
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.css
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ *
+ */
+
+.m-20 {
+ margin: 20px;
+}
+
+.h-100 {
+ height:100%;
+}
diff --git a/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.html b/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.html
new file mode 100644
index 0000000..682418b
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.html
@@ -0,0 +1,35 @@
+<!--
+ ~ 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" class="m-20">
+ <div fxLayout="row wrap" style="margin-bottom:20px;" *ngIf="editMode">
+ <button mat-button mat-raised-button color="primary" (click)="updateDashboardAndCloseEditMode()"
+ style="margin-right:10px;">Save
+ </button>
+ <button mat-button mat-raised-button class="mat-basic" (click)="discardChanges()"
+ style="margin-right:10px;">Discard
+ </button>
+ <button mat-button mat-raised-button color="primary" (click)="addWidget()" [disabled]="!editMode">Add
+ visualization</button>
+ </div>
+
+ <dashboard-grid [editMode]="editMode" [dashboard]="dashboard"
+ (updateCallback)="updateAndQueueItemForDeletion($event)"
+ (deleteCallback)="removeAndQueueItemForDeletion($event)"
+ class="h-100"></dashboard-grid>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.ts b/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.ts
new file mode 100644
index 0000000..8b4895f
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/panel/dashboard-panel.component.ts
@@ -0,0 +1,128 @@
+/*
+ * 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, EventEmitter, Input, OnInit, Output} from "@angular/core";
+import {Dashboard, DashboardItem} from "../../models/dashboard.model";
+import {forkJoin, Observable, Subscription} from "rxjs";
+import {MatDialog} from "@angular/material/dialog";
+import {AddVisualizationDialogComponent} from "../../dialogs/add-widget/add-visualization-dialog.component";
+import {DashboardWidget} from "../../../core-model/dashboard/DashboardWidget";
+import {DashboardService} from "../../services/dashboard.service";
+import {RefreshDashboardService} from "../../services/refresh-dashboard.service";
+
+@Component({
+ selector: 'dashboard-panel',
+ templateUrl: './dashboard-panel.component.html',
+ styleUrls: ['./dashboard-panel.component.css']
+})
+export class DashboardPanelComponent implements OnInit {
+
+ @Input() dashboard: Dashboard;
+ @Input("editMode") editMode: boolean;
+ @Output("editModeChange") editModeChange: EventEmitter<boolean> = new EventEmitter();
+
+ public items: DashboardItem[];
+
+ protected subscription: Subscription;
+
+ widgetIdsToRemove: Array<string> = [];
+ widgetsToUpdate: Map<string, DashboardWidget> = new Map<string, DashboardWidget>();
+
+ constructor(private dashboardService: DashboardService,
+ public dialog: MatDialog,
+ private refreshDashboardService: RefreshDashboardService) {
+ }
+
+ public ngOnInit() {
+
+ }
+
+ addWidget(): void {
+ const dialogRef = this.dialog.open(AddVisualizationDialogComponent, {
+ width: '70%',
+ height: '500px',
+ panelClass: 'custom-dialog-container'
+ });
+
+ dialogRef.afterClosed().subscribe(widget => {
+ if (widget) {
+ this.addWidgetToDashboard(widget);
+ }
+ });
+ }
+
+ addWidgetToDashboard(widget: DashboardWidget) {
+ let dashboardItem = {} as DashboardItem;
+ dashboardItem.widgetId = widget._id;
+ dashboardItem.id = widget._id;
+ // TODO there should be a widget type DashboardWidget
+ dashboardItem.widgetType = widget.dashboardWidgetSettings.widgetName;
+ dashboardItem.cols = 2;
+ dashboardItem.rows = 2;
+ dashboardItem.x = 0;
+ dashboardItem.y = 0;
+ this.dashboard.widgets.push(dashboardItem);
+ }
+
+ updateDashboardAndCloseEditMode() {
+ this.dashboardService.updateDashboard(this.dashboard).subscribe(result => {
+ if (this.widgetsToUpdate.size > 0) {
+ forkJoin(this.prepareWidgetUpdates()).subscribe(result => {
+ this.closeEditModeAndReloadDashboard();
+ });
+ } else {
+ this.deleteWidgets();
+ this.closeEditModeAndReloadDashboard()
+ }
+ })
+ }
+
+ closeEditModeAndReloadDashboard() {
+ this.editModeChange.emit(!(this.editMode));
+ this.refreshDashboardService.notify(this.dashboard._id);
+ }
+
+ prepareWidgetUpdates(): Array<Observable<any>> {
+ let promises: Array<Observable<any>> = [];
+ this.widgetsToUpdate.forEach((widget, key) => {
+ promises.push(this.dashboardService.updateWidget(widget));
+ })
+
+ return promises;
+ }
+
+ discardChanges() {
+ this.editModeChange.emit(!(this.editMode));
+ this.refreshDashboardService.notify(this.dashboard._id);
+ }
+
+ removeAndQueueItemForDeletion(widget: DashboardItem) {
+ this.dashboard.widgets.splice(this.dashboard.widgets.indexOf(widget), 1);
+ this.widgetIdsToRemove.push(widget.id);
+ }
+
+ updateAndQueueItemForDeletion(dashboardWidget: DashboardWidget) {
+ this.widgetsToUpdate.set(dashboardWidget._id, dashboardWidget);
+ }
+
+ deleteWidgets() {
+ this.widgetIdsToRemove.forEach(widgetId => {
+ this.dashboardService.deleteWidget(widgetId).subscribe();
+ });
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.css b/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.css
new file mode 100644
index 0000000..dea206d
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.css
@@ -0,0 +1,53 @@
+/*
+ * 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%;
+}
+
+.h-40 {
+ height:40px;
+}
+
+.p-0 {
+ padding:0;
+}
+
+.p-20 {
+ padding: 20px;
+}
+
+.m-0 {
+ margin:0;
+}
+
+.box {
+ display: flex;
+ flex-flow: column;
+ height: 100%;
+ border:0px solid black;
+}
+
+.box .row.content {
+ flex: 1 1 auto;
+}
+
+.box .row.header {
+ flex: 0 1 auto;
+}
+
diff --git a/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.html b/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.html
new file mode 100644
index 0000000..98851a7
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.html
@@ -0,0 +1,65 @@
+<!--
+ ~ 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 style="height:100%;">
+ <div class="box">
+ <div class="assemblyOptions sp-blue-bg m-0 row header h-40" *ngIf="editMode">
+ <div fxFlex="100" layout="row" fxLayoutAlign="end center">
+ <button mat-button mat-icon-button color="white" (click)="editWidget()">
+ <i class="material-icons">settings</i>
+ </button>
+ <button mat-button mat-icon-button color="white" (click)="removeWidget()">
+ <i class="material-icons">clear</i>
+ </button>
+ </div>
+ </div>
+ <div class="h-100 p-0 row content">
+ <!-- <div *ngIf="widget."></div>-->
+ <div *ngIf="widgetLoaded" class="h-100">
+ <div *ngIf="widget.widgetType === 'number'" class="h-100 p-0">
+ <number-widget [gridsterItemComponent]="gridsterItemComponent" [gridsterItem]="item"
+ [widget]="widget" [editMode]="editMode"
+ [widgetConfig]="configuredWidget" class="h-100"></number-widget>
+ </div>
+ <div *ngIf="widget.widgetType === 'line'" class="h-100 p-0">
+ <line-widget [gridsterItemComponent]="gridsterItemComponent" [editMode]="editMode"
+ [gridsterItem]="item" [widget]="widget" [widgetConfig]="configuredWidget" class="h-100"></line-widget>
+ </div>
+ <div *ngIf="widget.widgetType === 'area'" class="h-100 p-0">
+ <area-widget [gridsterItemComponent]="gridsterItemComponent" [editMode]="editMode"
+ [gridsterItem]="item" [widget]="widget" [widgetConfig]="configuredWidget" class="h-100"></area-widget>
+ </div>
+ <div *ngIf="widget.widgetType === 'table'" class="h-100 p-0">
+ <table-widget [gridsterItemComponent]="gridsterItemComponent"
+ [gridsterItem]="item" [widget]="widget" [editMode]="editMode"
+ [widgetConfig]="configuredWidget" class="h-100"></table-widget>
+ </div>
+ <div *ngIf="widget.widgetType === 'gauge'" class="h-100 p-0">
+ <gauge-widget [gridsterItemComponent]="gridsterItemComponent"
+ [gridsterItem]="item" [widget]="widget" [editMode]="editMode"
+ [widgetConfig]="configuredWidget" class="h-100"></gauge-widget>
+ </div>
+ <div *ngIf="widget.widgetType === 'image'" class="h-100 p-0">
+ <image-widget [gridsterItemComponent]="gridsterItemComponent"
+ [gridsterItem]="item" [widget]="widget" [editMode]="editMode"
+ [widgetConfig]="configuredWidget" class="h-100"></image-widget>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.ts b/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.ts
new file mode 100644
index 0000000..60a480a
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widget/dashboard-widget.component.ts
@@ -0,0 +1,81 @@
+/*
+ * 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 {AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output} from "@angular/core";
+import {Dashboard, DashboardItem} from "../../models/dashboard.model";
+import {DashboardService} from "../../services/dashboard.service";
+import {DashboardImageComponent} from "../../../app-transport-monitoring/components/dashboard-image/dashboard-image.component";
+import {DashboardWidget} from "../../../core-model/dashboard/DashboardWidget";
+import {Subject} from "rxjs";
+import {GridsterItem, GridsterItemComponent} from "angular-gridster2";
+import {GridsterInfo} from "../../models/gridster-info.model";
+import {ResizeService} from "../../services/resize.service";
+import {AddVisualizationDialogComponent} from "../../dialogs/add-widget/add-visualization-dialog.component";
+import {MatDialog} from "@angular/material/dialog";
+
+@Component({
+ selector: 'dashboard-widget',
+ templateUrl: './dashboard-widget.component.html',
+ styleUrls: ['./dashboard-widget.component.css']
+})
+export class DashboardWidgetComponent implements OnInit {
+
+ @Input() widget: DashboardItem;
+ @Input() editMode: boolean;
+ @Input() item: GridsterItem;
+ @Input() gridsterItemComponent: GridsterItemComponent;
+
+ @Output() deleteCallback: EventEmitter<DashboardItem> = new EventEmitter<DashboardItem>();
+ @Output() updateCallback: EventEmitter<DashboardWidget> = new EventEmitter<DashboardWidget>();
+
+ widgetLoaded: boolean = false;
+ configuredWidget: DashboardWidget;
+
+ constructor(private dashboardService: DashboardService,
+ private dialog: MatDialog) {
+ }
+
+ ngOnInit(): void {
+ this.dashboardService.getWidget(this.widget.id).subscribe(response => {
+ this.configuredWidget = response;
+ this.widgetLoaded = true;
+ });
+ }
+
+ removeWidget() {
+ this.deleteCallback.emit(this.widget);
+ }
+
+ editWidget(): void {
+ const dialogRef = this.dialog.open(AddVisualizationDialogComponent, {
+ width: '70%',
+ height: '500px',
+ panelClass: 'custom-dialog-container',
+ data: {
+ "widget": this.configuredWidget
+ }
+ });
+
+ dialogRef.afterClosed().subscribe(widget => {
+ if (widget) {
+ this.configuredWidget = widget;
+ this.updateCallback.emit(this.configuredWidget);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/area/area-config.ts b/ui/src/app/data-explorer-v2/components/widgets/area/area-config.ts
new file mode 100644
index 0000000..23d01a7
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/area/area-config.ts
@@ -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.
+ *
+ */
+
+import {BaseNgxLineConfig} from "../base/base-ngx-line-config";
+
+export class AreaConfig extends BaseNgxLineConfig {
+
+ getWidgetLabel(): string {
+ return "area";
+ }
+
+ getWidgetName(): string {
+ return "area";
+ }
+
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.css b/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.css
new file mode 100644
index 0000000..4215dfd
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.css
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+.title-panel {
+ font-size:20px;
+}
+
+.mt-20 {
+ margin-top:20px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.html b/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.html
new file mode 100644
index 0000000..9f9bbeb
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.html
@@ -0,0 +1,41 @@
+<!--
+ ~ 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-color': selectedBackgroundColor, 'color': selectedPrimaryTextColor}">
+ <div class="title-panel mt-20" *ngIf="hasTitlePanelSettings">
+ {{selectedTitle}}
+ </div>
+ <ngx-charts-area-chart *ngIf="displayChart"
+ [showXAxisLabel]="false"
+ [showYAxisLabel]="false"
+ [scheme]="colorScheme"
+ [timeline]="false"
+ [view]="view"
+ [autoScale]="false"
+ [xAxis]="true"
+ [yAxis]="true"
+ [yScaleMin]="minYAxisRange"
+ [yScaleMax]="maxYAxisRange"
+ [tooltipDisabled]="true"
+ [animations]="false"
+ [xAxisTickFormatting]="timestampTickFormatting"
+ [results]="multi" style="margin-top:10px;margin-bottom:10px;"
+ [ngStyle]="{'fill': selectedPrimaryTextColor}">
+ </ngx-charts-area-chart>
+</div>
+
diff --git a/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.ts b/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.ts
new file mode 100644
index 0000000..aaa6db0
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/area/area-widget.component.ts
@@ -0,0 +1,43 @@
+/*
+ * 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, OnDestroy, OnInit} from "@angular/core";
+import {BaseNgxLineChartsStreamPipesWidget} from "../base/base-ngx-line-charts-widget";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {ResizeService} from "../../../services/resize.service";
+
+@Component({
+ selector: 'area-widget',
+ templateUrl: './area-widget.component.html',
+ styleUrls: ['./area-widget.component.css']
+})
+export class AreaWidgetComponent extends BaseNgxLineChartsStreamPipesWidget implements OnInit, OnDestroy {
+
+ constructor(rxStompService: RxStompService, resizeService: ResizeService) {
+ super(rxStompService, resizeService);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/base/base-config.ts b/ui/src/app/data-explorer-v2/components/widgets/base/base-config.ts
new file mode 100644
index 0000000..fc221cb
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/base/base-config.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 {DashboardWidgetSettings} from "../../../../core-model/dashboard/DashboardWidgetSettings";
+
+export abstract class WidgetConfig {
+
+ abstract getConfig(): DashboardWidgetSettings;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-charts-widget.ts b/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-charts-widget.ts
new file mode 100644
index 0000000..619bd3d
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-charts-widget.ts
@@ -0,0 +1,74 @@
+/*
+ * 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 {BaseStreamPipesWidget} from "./base-widget";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {ResizeService} from "../../../services/resize.service";
+import {GridsterInfo} from "../../../models/gridster-info.model";
+import {GridsterItemComponent} from "angular-gridster2";
+
+export abstract class BaseNgxChartsStreamPipesWidget extends BaseStreamPipesWidget {
+
+ view: any[] = [];
+ displayChart: boolean = false;
+
+ colorScheme: any;
+
+ constructor(rxStompService: RxStompService, protected resizeService: ResizeService) {
+ super(rxStompService);
+ }
+
+ ngOnInit() {
+ super.ngOnInit();
+ this.colorScheme = {domain: [this.selectedSecondaryTextColor, this.selectedPrimaryTextColor]};
+ this.view = [this.computeCurrentWidth(this.gridsterItemComponent),
+ this.computeCurrentHeight(this.gridsterItemComponent)];
+ this.displayChart = true;
+ this.resizeService.resizeSubject.subscribe(info => {
+ this.onResize(info);
+ });
+ }
+
+ onResize(info: GridsterInfo) {
+ if (info.gridsterItem.id === this.gridsterItem.id) {
+ setTimeout(() => {
+ this.displayChart = false;
+ this.view = [this.computeCurrentWidth(info.gridsterItemComponent),
+ this.computeCurrentHeight(info.gridsterItemComponent)];
+ this.displayChart = true;
+ }, 100);
+ }
+ }
+
+ computeCurrentWidth(gridsterItemComponent: GridsterItemComponent): number {
+ return (gridsterItemComponent.width - (BaseNgxChartsStreamPipesWidget.PADDING * 2));
+ }
+
+ computeCurrentHeight(gridsterItemComponent: GridsterItemComponent): number {
+ return (gridsterItemComponent.height - (BaseNgxChartsStreamPipesWidget.PADDING * 2) - this.editModeOffset() - this.titlePanelOffset());
+ }
+
+ editModeOffset(): number {
+ return this.editMode ? BaseNgxChartsStreamPipesWidget.EDIT_HEADER_HEIGHT : 0;
+ }
+
+ titlePanelOffset(): number {
+ return this.hasTitlePanelSettings ? 20 : 0;
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-line-charts-widget.ts b/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-line-charts-widget.ts
new file mode 100644
index 0000000..03d0172
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-line-charts-widget.ts
@@ -0,0 +1,74 @@
+/*
+ * 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 {RxStompService} from "@stomp/ng2-stompjs";
+import {ResizeService} from "../../../services/resize.service";
+import {BaseNgxChartsStreamPipesWidget} from "./base-ngx-charts-widget";
+import {StaticPropertyExtractor} from "../../../sdk/extractor/static-property-extractor";
+import {LineConfig} from "../line/line-config";
+
+export abstract class BaseNgxLineChartsStreamPipesWidget extends BaseNgxChartsStreamPipesWidget {
+
+ multi:any = [];
+
+ selectedNumberProperty: string;
+ selectedTimestampProperty: string;
+ minYAxisRange: number;
+ maxYAxisRange: number;
+
+ constructor(rxStompService: RxStompService, resizeService: ResizeService) {
+ super(rxStompService, resizeService);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ this.multi = [
+ {
+ "name": this.selectedNumberProperty,
+ "series": [
+ ]
+ }];
+ }
+
+ protected extractConfig(extractor: StaticPropertyExtractor) {
+ this.selectedNumberProperty = extractor.mappingPropertyValue(LineConfig.NUMBER_MAPPING_KEY);
+ this.selectedTimestampProperty = extractor.mappingPropertyValue(LineConfig.TIMESTAMP_MAPPING_KEY);
+ this.minYAxisRange = extractor.integerParameter(LineConfig.MIN_Y_AXIS_KEY);
+ this.maxYAxisRange = extractor.integerParameter(LineConfig.MAX_Y_AXIS_KEY);
+ }
+
+ protected onEvent(event: any) {
+ let time = event[this.selectedTimestampProperty];
+ let value = event[this.selectedNumberProperty];
+ this.makeEvent(time, value);
+ }
+
+ makeEvent(time: any, value: any): void {
+ this.multi[0].series.push({"name": time, "value": value});
+ if (this.multi[0].series.length > 10) {
+ this.multi[0].series.shift();
+ }
+ this.multi = [...this.multi];
+ }
+
+ timestampTickFormatting(timestamp: any): string {
+ var date = new Date(timestamp);
+ let timeString = date.getHours() + ':' + date.getMinutes().toString().substr(-2) + ':' + date.getSeconds().toString().substr(-2);
+ return timeString;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-line-config.ts b/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-line-config.ts
new file mode 100644
index 0000000..143d4c1
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/base/base-ngx-line-config.ts
@@ -0,0 +1,47 @@
+/*
+ * 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 {WidgetConfig} from "./base-config";
+import {DashboardWidgetSettings} from "../../../../core-model/dashboard/DashboardWidgetSettings";
+import {WidgetConfigBuilder} from "../../../registry/widget-config-builder";
+import {SchemaRequirementsBuilder} from "../../../sdk/schema-requirements-builder";
+import {EpRequirements} from "../../../sdk/ep-requirements";
+
+export abstract class BaseNgxLineConfig extends WidgetConfig {
+
+ static readonly NUMBER_MAPPING_KEY: string = "number-mapping";
+ static readonly TIMESTAMP_MAPPING_KEY: string = "timestamp-mapping";
+ static readonly MIN_Y_AXIS_KEY: string = "min-y-axis-key";
+ static readonly MAX_Y_AXIS_KEY: string = "max-y-axis-key";
+
+ getConfig(): DashboardWidgetSettings {
+ return WidgetConfigBuilder.createWithSelectableColorsAndTitlePanel(this.getWidgetName(), this.getWidgetLabel())
+ .requiredSchema(SchemaRequirementsBuilder
+ .create()
+ .requiredPropertyWithUnaryMapping(BaseNgxLineConfig.TIMESTAMP_MAPPING_KEY, "Timestamp field", "", EpRequirements.timestampReq())
+ .requiredPropertyWithUnaryMapping(BaseNgxLineConfig.NUMBER_MAPPING_KEY, "Number field", "", EpRequirements.numberReq())
+ .build())
+ .requiredIntegerParameter(BaseNgxLineConfig.MIN_Y_AXIS_KEY, "Y-axis range (min)", "")
+ .requiredIntegerParameter(BaseNgxLineConfig.MAX_Y_AXIS_KEY, "Y-axis range (min)", "")
+ .build();
+ }
+
+ abstract getWidgetName(): string;
+
+ abstract getWidgetLabel(): string;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/base/base-widget.ts b/ui/src/app/data-explorer-v2/components/widgets/base/base-widget.ts
new file mode 100644
index 0000000..79bd7da
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/base/base-widget.ts
@@ -0,0 +1,96 @@
+/*
+ * 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 {Input, OnChanges, OnInit, SimpleChanges} from "@angular/core";
+import {DashboardItem} from "../../../models/dashboard.model";
+import {DashboardWidget} from "../../../../core-model/dashboard/DashboardWidget";
+import {StaticPropertyExtractor} from "../../../sdk/extractor/static-property-extractor";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {Message} from "@stomp/stompjs";
+import {Subscription} from "rxjs";
+import {GridsterItem, GridsterItemComponent} from "angular-gridster2";
+import {WidgetConfigBuilder} from "../../../registry/widget-config-builder";
+
+export abstract class BaseStreamPipesWidget implements OnChanges {
+
+ @Input() widget: DashboardItem;
+ @Input() widgetConfig: DashboardWidget;
+ @Input() gridsterItem: GridsterItem;
+ @Input() gridsterItemComponent: GridsterItemComponent;
+ @Input() editMode: boolean;
+
+ static readonly PADDING: number = 20;
+ static readonly EDIT_HEADER_HEIGHT: number = 40;
+
+ subscription: Subscription;
+
+ hasSelectableColorSettings: boolean;
+ hasTitlePanelSettings: boolean;
+
+ selectedBackgroundColor: string;
+ selectedPrimaryTextColor: string;
+ selectedSecondaryTextColor: string;
+ selectedTitle: string;
+
+ defaultBackgroundColor: string = "#1B1464";
+ defaultPrimaryTextColor: string = "#FFFFFF";
+ defaultSecondaryTextColor: string = "#39B54A";
+
+ protected constructor(private rxStompService: RxStompService) {
+ }
+
+ ngOnInit(): void {
+ this.prepareConfigExtraction();
+ this.subscription = this.rxStompService.watch("/topic/" +this.widgetConfig.dashboardWidgetDataConfig.topic).subscribe((message: Message) => {
+ this.onEvent(JSON.parse(message.body));
+ });
+ }
+
+ prepareConfigExtraction() {
+ let extractor: StaticPropertyExtractor = new StaticPropertyExtractor(this.widgetConfig.dashboardWidgetDataConfig.schema, this.widgetConfig.dashboardWidgetSettings.config);
+ if (extractor.hasStaticProperty(WidgetConfigBuilder.BACKGROUND_COLOR_KEY)) {
+ this.hasSelectableColorSettings = true;
+ this.selectedBackgroundColor = extractor.selectedColor(WidgetConfigBuilder.BACKGROUND_COLOR_KEY);
+ this.selectedPrimaryTextColor = extractor.selectedColor(WidgetConfigBuilder.PRIMARY_TEXT_COLOR_KEY);
+ this.selectedSecondaryTextColor = extractor.selectedColor(WidgetConfigBuilder.SECONDARY_TEXT_COLOR_KEY);
+ } else {
+ this.selectedBackgroundColor = this.defaultBackgroundColor;
+ this.selectedPrimaryTextColor = this.defaultPrimaryTextColor;
+ this.selectedSecondaryTextColor = this.defaultSecondaryTextColor;
+ }
+ if (extractor.hasStaticProperty(WidgetConfigBuilder.TITLE_KEY)) {
+ this.hasTitlePanelSettings = true;
+ this.selectedTitle = extractor.stringParameter(WidgetConfigBuilder.TITLE_KEY);
+ }
+ this.extractConfig(extractor);
+ }
+
+ ngOnDestroy(): void {
+ this.subscription.unsubscribe();
+ }
+
+ protected abstract extractConfig(extractor: StaticPropertyExtractor);
+
+ protected abstract onEvent(event: any);
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes["widgetConfig"]) {
+ this.prepareConfigExtraction();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-config.ts b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-config.ts
new file mode 100644
index 0000000..76eb3a8
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-config.ts
@@ -0,0 +1,48 @@
+/*
+ * 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 {WidgetConfig} from "../base/base-config";
+import {DashboardWidgetSettings} from "../../../../core-model/dashboard/DashboardWidgetSettings";
+import {WidgetConfigBuilder} from "../../../registry/widget-config-builder";
+import {SchemaRequirementsBuilder} from "../../../sdk/schema-requirements-builder";
+import {EpRequirements} from "../../../sdk/ep-requirements";
+
+export class GaugeConfig extends WidgetConfig {
+
+ static readonly TITLE_KEY: string = "title-key";
+ static readonly NUMBER_MAPPING_KEY: string = "number-mapping";
+ static readonly COLOR_KEY: string = "color-key";
+ static readonly MIN_KEY: string = "min-key";
+ static readonly MAX_KEY: string = "max-key";
+
+ constructor() {
+ super();
+ }
+
+ getConfig(): DashboardWidgetSettings {
+ return WidgetConfigBuilder.createWithSelectableColorsAndTitlePanel("gauge", "gauge")
+ .requiredSchema(SchemaRequirementsBuilder
+ .create()
+ .requiredPropertyWithUnaryMapping(GaugeConfig.NUMBER_MAPPING_KEY, "Select property", "", EpRequirements.numberReq())
+ .build())
+ .requiredIntegerParameter(GaugeConfig.MIN_KEY, "Min Y axis value", "")
+ .requiredIntegerParameter(GaugeConfig.MAX_KEY, "Max Y axis value", "")
+ .build();
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.css b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.css
new file mode 100644
index 0000000..0dd319a
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.css
@@ -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.
+ *
+ */
+
+.main-panel {
+ width:100%;
+ height: 100%;
+ display:inline-grid;
+ align-content: center;
+}
+
+.mt-20 {
+ margin-top:20px;
+}
+
+.title-panel {
+ font-size:20px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.html b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.html
new file mode 100644
index 0000000..9b6c9ee
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.html
@@ -0,0 +1,36 @@
+<!--
+ ~ 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-color': selectedBackgroundColor, 'color': selectedPrimaryTextColor}">
+ <div class="title-panel mt-20" *ngIf="hasTitlePanelSettings">
+ {{selectedTitle}}
+ </div>
+ <ngx-charts-gauge
+ [view]="view"
+ [scheme]="colorScheme"
+ [results]="data"
+ [min]="min"
+ [max]="max"
+ [angleSpan]="240"
+ [startAngle]="-120"
+ [bigSegments]="10"
+ [smallSegments]="5"
+ [ngStyle]="{'fill': selectedPrimaryTextColor}" *ngIf="displayChart">
+ </ngx-charts-gauge>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.ts b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.ts
new file mode 100644
index 0000000..479da83
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/gauge/gauge-widget.component.ts
@@ -0,0 +1,67 @@
+/*
+ * 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 {AfterViewInit, Component, ElementRef, OnDestroy, OnInit} from "@angular/core";
+import {BaseNgxChartsStreamPipesWidget} from "../base/base-ngx-charts-widget";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {ResizeService} from "../../../services/resize.service";
+import {StaticPropertyExtractor} from "../../../sdk/extractor/static-property-extractor";
+import {GaugeConfig} from "./gauge-config";
+
+
+@Component({
+ selector: 'gauge-widget',
+ templateUrl: './gauge-widget.component.html',
+ styleUrls: ['./gauge-widget.component.css']
+})
+export class GaugeWidgetComponent extends BaseNgxChartsStreamPipesWidget implements OnInit, OnDestroy {
+
+ data: any = [];
+ min: number;
+ max: number;
+
+ selectedProperty: string;
+
+ constructor(rxStompService: RxStompService, resizeService: ResizeService, private el: ElementRef) {
+ super(rxStompService, resizeService);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+ extractConfig(extractor: StaticPropertyExtractor) {
+ this.min = extractor.integerParameter(GaugeConfig.MIN_KEY);
+ this.max = extractor.integerParameter(GaugeConfig.MAX_KEY);
+ this.selectedProperty = extractor.mappingPropertyValue(GaugeConfig.NUMBER_MAPPING_KEY);
+ }
+
+ isNumber(item: any): boolean {
+ return false;
+ }
+
+ protected onEvent(event: any) {
+ this.data[0] = ({"name": "value", "value": event[this.selectedProperty]});
+ this.data = [...this.data];
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/image/image-config.ts b/ui/src/app/data-explorer-v2/components/widgets/image/image-config.ts
new file mode 100644
index 0000000..20e3086
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/image/image-config.ts
@@ -0,0 +1,44 @@
+/*
+ * 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 {WidgetConfig} from "../base/base-config";
+import {DashboardWidgetSettings} from "../../../../core-model/dashboard/DashboardWidgetSettings";
+import {WidgetConfigBuilder} from "../../../registry/widget-config-builder";
+import {SchemaRequirementsBuilder} from "../../../sdk/schema-requirements-builder";
+import {EpRequirements} from "../../../sdk/ep-requirements";
+
+export class ImageConfig extends WidgetConfig {
+
+ static readonly TITLE_KEY: string = "title-key";
+ static readonly NUMBER_MAPPING_KEY: string = "number-mapping";
+
+ constructor() {
+ super();
+ }
+
+ getConfig(): DashboardWidgetSettings {
+ return WidgetConfigBuilder.create("image", "image")
+ .requiredSchema(SchemaRequirementsBuilder
+ .create()
+ .requiredPropertyWithUnaryMapping(ImageConfig.NUMBER_MAPPING_KEY, "Select property", "", EpRequirements.imageReq())
+ .build())
+ .requiredTextParameter(ImageConfig.TITLE_KEY, "Title", "The title")
+ .build();
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.css b/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.css
new file mode 100644
index 0000000..340d4a7
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.css
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ *
+ */
+
+.image-box {
+ width:100%;
+ height: 100%;
+ color: #fff;
+ text-align: center;
+ left: 50%;
+ display:inline-grid;
+ align-content: center;
+}
+
+.image-title {
+ font-size:14px;
+}
diff --git a/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.html b/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.html
new file mode 100644
index 0000000..ea6be46
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.html
@@ -0,0 +1,26 @@
+<!--
+ ~ 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 class="image-box" [ngStyle]="{'background-color': 'white'}">
+ <div class="imageTitle">
+ {{title}}
+ </div>
+ <div class="imageContent">
+ <img style="width: 100%;" src="data:image/jpg;base64,{{item}}" *ngIf="item" />
+ </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.ts b/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.ts
new file mode 100644
index 0000000..6725eea
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/image/image-widget.component.ts
@@ -0,0 +1,62 @@
+/*
+ * 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, OnDestroy, OnInit} from "@angular/core";
+import {BaseNgxChartsStreamPipesWidget} from "../base/base-ngx-charts-widget";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {ResizeService} from "../../../services/resize.service";
+import {StaticPropertyExtractor} from "../../../sdk/extractor/static-property-extractor";
+import {GaugeConfig} from "../gauge/gauge-config";
+
+@Component({
+ selector: 'image-widget',
+ templateUrl: './image-widget.component.html',
+ styleUrls: ['./image-widget.component.css']
+})
+export class ImageWidgetComponent extends BaseNgxChartsStreamPipesWidget implements OnInit, OnDestroy {
+
+ item: any;
+ title: string;
+ selectedProperty: string;
+
+ constructor(rxStompService: RxStompService, resizeService: ResizeService) {
+ super(rxStompService, resizeService);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+ extractConfig(extractor: StaticPropertyExtractor) {
+ this.title = extractor.singleValueParameter(GaugeConfig.TITLE_KEY);
+ this.selectedProperty = extractor.mappingPropertyValue(GaugeConfig.NUMBER_MAPPING_KEY);
+ }
+
+ isNumber(item: any): boolean {
+ return false;
+ }
+
+ protected onEvent(event: any) {
+ this.item = event[this.selectedProperty];
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/line/line-config.ts b/ui/src/app/data-explorer-v2/components/widgets/line/line-config.ts
new file mode 100644
index 0000000..da45420
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/line/line-config.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 {BaseNgxLineConfig} from "../base/base-ngx-line-config";
+
+export class LineConfig extends BaseNgxLineConfig {
+
+ getWidgetLabel(): string {
+ return "line";
+ }
+
+ getWidgetName(): string {
+ return "line";
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.css b/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.css
new file mode 100644
index 0000000..0dd319a
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.css
@@ -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.
+ *
+ */
+
+.main-panel {
+ width:100%;
+ height: 100%;
+ display:inline-grid;
+ align-content: center;
+}
+
+.mt-20 {
+ margin-top:20px;
+}
+
+.title-panel {
+ font-size:20px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.html b/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.html
new file mode 100644
index 0000000..e3eea5f
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.html
@@ -0,0 +1,41 @@
+<!--
+ ~ 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-color': selectedBackgroundColor, 'color': selectedPrimaryTextColor}">
+ <div class="title-panel mt-20" *ngIf="hasTitlePanelSettings">
+ {{selectedTitle}}
+ </div>
+ <ngx-charts-line-chart *ngIf="displayChart"
+ [showXAxisLabel]="false"
+ [showYAxisLabel]="false"
+ [scheme]="colorScheme"
+ [timeline]="false"
+ [view]="view"
+ [autoScale]="false"
+ [xAxis]="true"
+ [yAxis]="true"
+ [yScaleMin]="minYAxisRange"
+ [yScaleMax]="maxYAxisRange"
+ [tooltipDisabled]="true"
+ [animations]="false"
+ [xAxisTickFormatting]="timestampTickFormatting"
+ [results]="multi" style="margin-top:10px;margin-bottom:10px;"
+ [ngStyle]="{'fill': selectedPrimaryTextColor}">
+ </ngx-charts-line-chart>
+</div>
+
diff --git a/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.ts b/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.ts
new file mode 100644
index 0000000..31d4ff2
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/line/line-widget.component.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 {AfterViewInit, Component, ElementRef, OnDestroy, OnInit} from "@angular/core";
+import {StaticPropertyExtractor} from "../../../sdk/extractor/static-property-extractor";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {LineConfig} from "./line-config";
+import {ResizeService} from "../../../services/resize.service";
+import {BaseNgxChartsStreamPipesWidget} from "../base/base-ngx-charts-widget";
+import {BaseNgxLineChartsStreamPipesWidget} from "../base/base-ngx-line-charts-widget";
+
+@Component({
+ selector: 'line-widget',
+ templateUrl: './line-widget.component.html',
+ styleUrls: ['./line-widget.component.css']
+})
+export class LineWidgetComponent extends BaseNgxLineChartsStreamPipesWidget implements OnInit, OnDestroy {
+
+ constructor(rxStompService: RxStompService, resizeService: ResizeService) {
+ super(rxStompService, resizeService);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/number/number-config.ts b/ui/src/app/data-explorer-v2/components/widgets/number/number-config.ts
new file mode 100644
index 0000000..f4f0b81
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/number/number-config.ts
@@ -0,0 +1,42 @@
+/*
+ * 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 {WidgetConfigBuilder} from "../../../registry/widget-config-builder";
+import {SchemaRequirementsBuilder} from "../../../sdk/schema-requirements-builder";
+import {EpRequirements} from "../../../sdk/ep-requirements";
+import {DashboardWidgetSettings} from "../../../../core-model/dashboard/DashboardWidgetSettings";
+import {WidgetConfig} from "../base/base-config";
+
+export class NumberConfig extends WidgetConfig {
+
+ static readonly NUMBER_MAPPING_KEY: string = "number-mapping";
+
+ constructor() {
+ super();
+ }
+
+ getConfig(): DashboardWidgetSettings {
+ return WidgetConfigBuilder.createWithSelectableColorsAndTitlePanel("number", "number")
+ .requiredSchema(SchemaRequirementsBuilder
+ .create()
+ .requiredPropertyWithUnaryMapping(NumberConfig.NUMBER_MAPPING_KEY, "Select property", "", EpRequirements.numberReq())
+ .build())
+ .build();
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.css b/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.css
new file mode 100644
index 0000000..eaf8444
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.css
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ *
+ */
+
+.circleNumber {
+ width:100%;
+ height: 100%;
+ text-align: center;
+ left: 50%;
+ display:inline-grid;
+ align-content: center;
+}
+
+
+.numberItem {
+ font-size:60px;
+ font-weight:bold;
+}
+
+.title-panel {
+ font-size:20px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.html b/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.html
new file mode 100644
index 0000000..0550f87
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.html
@@ -0,0 +1,27 @@
+<!--
+ ~ 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 class="circleNumber" [ngStyle]="{'background-color': selectedBackgroundColor, 'color': selectedPrimaryTextColor}">
+ <div class="title-panel" *ngIf="hasTitlePanelSettings">
+ {{selectedTitle}}
+ </div>
+ <div class="numberItem">
+ <div *ngIf="isNumber(item)">{{item}}</div>
+ <div *ngIf="!isNumber(item)">{{item}}</div>
+ </div>
+</div>
diff --git a/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.ts b/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.ts
new file mode 100644
index 0000000..7157be8
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/number/number-widget.component.ts
@@ -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.
+ *
+ */
+
+import {Component, Input, OnDestroy, OnInit} from "@angular/core";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {BaseStreamPipesWidget} from "../base/base-widget";
+import {StaticPropertyExtractor} from "../../../sdk/extractor/static-property-extractor";
+import {NumberConfig} from "./number-config";
+
+@Component({
+ selector: 'number-widget',
+ templateUrl: './number-widget.component.html',
+ styleUrls: ['./number-widget.component.css']
+})
+export class NumberWidgetComponent extends BaseStreamPipesWidget implements OnInit, OnDestroy {
+
+ item: any;
+
+ selectedProperty: string;
+
+ constructor(rxStompService: RxStompService) {
+ super(rxStompService);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+ extractConfig(extractor: StaticPropertyExtractor) {
+ this.selectedProperty = extractor.mappingPropertyValue(NumberConfig.NUMBER_MAPPING_KEY);
+ }
+
+ isNumber(item: any): boolean {
+ return false;
+ }
+
+ protected onEvent(event: any) {
+ this.item = event[this.selectedProperty];
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/table/table-config.ts b/ui/src/app/data-explorer-v2/components/widgets/table/table-config.ts
new file mode 100644
index 0000000..47b71f5
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/table/table-config.ts
@@ -0,0 +1,44 @@
+/*
+ * 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 {WidgetConfig} from "../base/base-config";
+import {DashboardWidgetSettings} from "../../../../core-model/dashboard/DashboardWidgetSettings";
+import {WidgetConfigBuilder} from "../../../registry/widget-config-builder";
+import {SchemaRequirementsBuilder} from "../../../sdk/schema-requirements-builder";
+import {EpRequirements} from "../../../sdk/ep-requirements";
+
+export class TableConfig extends WidgetConfig {
+
+ static readonly TITLE_KEY: string = "title-key";
+ static readonly SELECTED_PROPERTIES_KEYS: string = "selected-fields-key";
+
+ constructor() {
+ super();
+ }
+
+ getConfig(): DashboardWidgetSettings {
+ return WidgetConfigBuilder.createWithSelectableColorsAndTitlePanel("table", "table")
+ .requiredSchema(SchemaRequirementsBuilder
+ .create()
+ .requiredPropertyWithNaryMapping(TableConfig.SELECTED_PROPERTIES_KEYS, "Select properties", "", EpRequirements.anyProperty())
+ .build())
+ .requiredTextParameter(TableConfig.TITLE_KEY, "Title", "The title")
+ .build();
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.css b/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.css
new file mode 100644
index 0000000..59023f4
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.css
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ *
+ */
+
+.title-panel {
+ font-size:20px;
+ text-align:center;
+}
+
+.mt-20 {
+ margin-top:20px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.html b/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.html
new file mode 100644
index 0000000..dc55f14
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.html
@@ -0,0 +1,36 @@
+<!--
+ ~ 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-color': selectedBackgroundColor, 'color':
+selectedPrimaryTextColor}">
+ <div class="title-panel mt-20" *ngIf="hasTitlePanelSettings">
+ {{selectedTitle}}
+ </div>
+ <table fxFlex="100" mat-table [dataSource]="dataSource" [ngStyle]="{'background': selectedBackgroundColor}">
+
+ <ng-container *ngFor="let element of selectedProperties" [cdkColumnDef]="element">
+ <th mat-header-cell [ngStyle]="{'color': selectedPrimaryTextColor}"
+ *matHeaderCellDef><label>{{element}}</label></th>
+ <td mat-cell *matCellDef="let row" [ngStyle]="{'color': selectedPrimaryTextColor}">{{row[element]}}</td>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="selectedProperties; sticky: true"></tr>
+ <tr mat-row *matRowDef="let row; columns: selectedProperties;"></tr>
+
+ </table>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.ts b/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.ts
new file mode 100644
index 0000000..56c970b
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/components/widgets/table/table-widget.component.ts
@@ -0,0 +1,77 @@
+/*
+ * 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, OnDestroy, OnInit} from "@angular/core";
+import {BaseStreamPipesWidget} from "../base/base-widget";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {StaticPropertyExtractor} from "../../../sdk/extractor/static-property-extractor";
+import {MatTableDataSource} from "@angular/material/table";
+import {TableConfig} from "./table-config";
+import {SemanticTypeUtilsService} from "../../../../core-services/semantic-type/semantic-type-utils.service";
+
+@Component({
+ selector: 'table-widget',
+ templateUrl: './table-widget.component.html',
+ styleUrls: ['./table-widget.component.css']
+})
+export class TableWidgetComponent extends BaseStreamPipesWidget implements OnInit, OnDestroy {
+
+ selectedProperties: Array<string>;
+
+ displayedColumns: String[] = [];
+ dataSource = new MatTableDataSource();
+ semanticTypes: { [key: string]: string; } = {};
+
+ constructor(rxStompService: RxStompService, private semanticTypeUtils: SemanticTypeUtilsService) {
+ super(rxStompService);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+
+ this.widgetConfig.dashboardWidgetDataConfig.schema.eventProperties.forEach((key, index) => {
+ this.semanticTypes[key.runtimeName] = key.domainProperty
+ });
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+ extractConfig(extractor: StaticPropertyExtractor) {
+ this.selectedProperties = extractor.mappingPropertyValues(TableConfig.SELECTED_PROPERTIES_KEYS);
+ }
+
+ protected onEvent(event: any) {
+ this.dataSource.data.unshift(this.createTableObject(event));
+ if (this.dataSource.data.length > 10) {
+ this.dataSource.data.pop();
+ }
+ this.dataSource.data = [...this.dataSource.data];
+ }
+
+ createTableObject(event: any) {
+ let object = {};
+ this.selectedProperties.forEach((key, index) => {
+ event[key] = this.semanticTypeUtils.getValue(event[key], this.semanticTypes[key]);
+ object[key] = event[key];
+ });
+ return object;
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/data-explorer-v2.component.css b/ui/src/app/data-explorer-v2/data-explorer-v2.component.css
new file mode 100644
index 0000000..7eaab26
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/data-explorer-v2.component.css
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ *
+ */
+
+.mr-20 {
+ margin-right:20px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/data-explorer-v2.component.html b/ui/src/app/data-explorer-v2/data-explorer-v2.component.html
new file mode 100644
index 0000000..6bb288d
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/data-explorer-v2.component.html
@@ -0,0 +1,51 @@
+<!--
+ ~ 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" class="page-container">
+ <div fxLayout="row" style="padding:0px;background-color:#f6f6f6;">
+ <div fxFlex="100" style="line-height:24px;border-bottom:1px solid #ccc">
+ <div fxFlex="100" fxLayout="row">
+ <div fxFlex fxLayoutAlign="start center">
+ <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectDashboard($event)">
+ <mat-tab label="Start"></mat-tab>
+ <mat-tab *ngFor="let dashboard of dashboards" label="{{dashboard.name}}"></mat-tab>
+ </mat-tab-group>
+ </div>
+ <div fxFlex fxLayoutAlign="end center" class="mr-20">
+ <button mat-button mat-icon-button color="primary"
+ *ngIf="selectedIndex > 0" (click)="toggleEditMode()" [disabled]="editMode">
+ <i class="material-icons">edit</i>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="fixed-height page-container-padding-inner" fxLayout="column" fxFlex="100" *ngIf="dashboardsLoaded">
+ <dashboard-overview (selectDashboardEmitter)="openDashboard($event)"
+ (reloadDashboardsEmitter)="getDashboards()"
+ [dashboards]="dashboards"
+ *ngIf="!dashboardTabSelected">
+
+ </dashboard-overview>
+ <dashboard-panel fxLayout="column" [(editMode)]="editMode" [dashboard]="selectedDashboard"
+ style="height:100%;" *ngIf="dashboardTabSelected">
+
+ </dashboard-panel>
+ </div>
+</div>
diff --git a/ui/src/app/data-explorer-v2/data-explorer-v2.component.ts b/ui/src/app/data-explorer-v2/data-explorer-v2.component.ts
new file mode 100644
index 0000000..eab8564
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/data-explorer-v2.component.ts
@@ -0,0 +1,83 @@
+/*
+ * 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 { Dashboard } from './models/dashboard.model';
+import { DashboardService } from './services/dashboard.service';
+import { RefreshDashboardService } from './services/refresh-dashboard.service';
+
+@Component({
+ selector: 'data-explorer-v2',
+ templateUrl: './data-explorer-v2.component.html',
+ styleUrls: ['./data-explorer-v2.component.css']
+})
+export class DataExplorerV2Component implements OnInit {
+
+ selectedDashboard: Dashboard;
+ selectedIndex = 0;
+ dashboardsLoaded = false;
+ dashboardTabSelected = false;
+
+ editMode = false;
+
+ dashboards: Dashboard[];
+
+ constructor(private dashboardService: DashboardService,
+ private refreshDashboardService: RefreshDashboardService) {}
+
+ public ngOnInit() {
+ this.getDashboards();
+ this.refreshDashboardService.refreshSubject.subscribe(currentDashboardId => {
+ this.getDashboards(currentDashboardId);
+ });
+
+ }
+
+ openDashboard(dashboard: Dashboard) {
+ const index = this.dashboards.indexOf(dashboard);
+ this.selectDashboard((index + 1));
+ }
+
+ selectDashboard(index: number) {
+ this.selectedIndex = index;
+ if (index == 0) {
+ this.dashboardTabSelected = false;
+ } else {
+ this.dashboardTabSelected = true;
+ this.selectedDashboard = this.dashboards[(index - 1)];
+ }
+ }
+
+ protected getDashboards(currentDashboardId?: string) {
+ this.dashboardsLoaded = false;
+ this.dashboardService.getDashboards().subscribe(data => {
+ this.dashboards = data;
+ if (currentDashboardId) {
+ const currentDashboard = this.dashboards.find(d => d._id === currentDashboardId);
+ this.selectDashboard(this.dashboards.indexOf(currentDashboard) + 1);
+ } else {
+ this.selectedIndex = 0;
+ }
+ this.dashboardsLoaded = true;
+ });
+ }
+
+ toggleEditMode() {
+ this.editMode = ! (this.editMode);
+ }
+}
diff --git a/ui/src/app/data-explorer-v2/data-explorer-v2.module.ts b/ui/src/app/data-explorer-v2/data-explorer-v2.module.ts
new file mode 100644
index 0000000..1e4d678
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/data-explorer-v2.module.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 { CdkTableModule } from '@angular/cdk/table';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { FormsModule } from '@angular/forms';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { MatTabsModule } from '@angular/material/tabs';
+import { InjectableRxStompConfig, RxStompService, rxStompServiceFactory } from '@stomp/ng2-stompjs';
+import { NgxChartsModule } from '@swimlane/ngx-charts';
+import { GridsterModule } from 'angular-gridster2';
+import { DynamicModule } from 'ng-dynamic-component';
+import { ColorPickerModule } from 'ngx-color-picker';
+import { ConnectModule } from '../connect/connect.module';
+import { SemanticTypeUtilsService } from '../core-services/semantic-type/semantic-type-utils.service';
+import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
+import { ElementIconText } from '../services/get-element-icon-text.service';
+import { DashboardGridComponent } from './components/grid/dashboard-grid.component';
+import { DashboardOverviewComponent } from './components/overview/dashboard-overview.component';
+import { DashboardPanelComponent } from './components/panel/dashboard-panel.component';
+import { DashboardWidgetComponent } from './components/widget/dashboard-widget.component';
+import { AreaWidgetComponent } from './components/widgets/area/area-widget.component';
+import { GaugeWidgetComponent } from './components/widgets/gauge/gauge-widget.component';
+import { ImageWidgetComponent } from './components/widgets/image/image-widget.component';
+import { LineWidgetComponent } from './components/widgets/line/line-widget.component';
+import { NumberWidgetComponent } from './components/widgets/number/number-widget.component';
+import { TableWidgetComponent } from './components/widgets/table/table-widget.component';
+import { DataExplorerV2Component } from './data-explorer-v2.component';
+import { AddVisualizationDialogComponent } from './dialogs/add-widget/add-visualization-dialog.component';
+import { EditDashboardDialogComponent } from './dialogs/edit-dashboard/edit-dashboard-dialog.component';
+import { DashboardService } from './services/dashboard.service';
+import { RefreshDashboardService } from './services/refresh-dashboard.service';
+import { ResizeService } from './services/resize.service';
+import { streamPipesStompConfig } from './services/websocket.config';
+
+const dashboardWidgets = [
+
+];
+
+@NgModule({
+ imports: [
+ CommonModule,
+ MatTabsModule,
+ DynamicModule.withComponents(
+ dashboardWidgets
+ ),
+ FlexLayoutModule,
+ GridsterModule,
+ CommonModule,
+ FlexLayoutModule,
+ CustomMaterialModule,
+ FormsModule,
+ ColorPickerModule,
+ MatGridListModule,
+ ConnectModule,
+ NgxChartsModule,
+ CdkTableModule,
+ ],
+ declarations: [
+ DataExplorerV2Component,
+ DashboardGridComponent,
+ DashboardOverviewComponent,
+ DashboardPanelComponent,
+ DashboardWidgetComponent,
+ AddVisualizationDialogComponent,
+ EditDashboardDialogComponent,
+ AreaWidgetComponent,
+ LineWidgetComponent,
+ NumberWidgetComponent,
+ TableWidgetComponent,
+ GaugeWidgetComponent,
+ ImageWidgetComponent
+ ],
+ providers: [
+ DashboardService,
+ ResizeService,
+ RefreshDashboardService,
+ SemanticTypeUtilsService,
+ {
+ provide: 'RestApi',
+ useFactory: ($injector: any) => $injector.get('RestApi'),
+ deps: ['$injector'],
+ },
+ ElementIconText,
+ {
+ provide: InjectableRxStompConfig,
+ useValue: streamPipesStompConfig
+ },
+ {
+ provide: RxStompService,
+ useFactory: rxStompServiceFactory,
+ deps: [InjectableRxStompConfig]
+ }
+ ],
+ exports: [
+ DataExplorerV2Component
+ ],
+ entryComponents: [
+ DataExplorerV2Component,
+ AddVisualizationDialogComponent,
+ EditDashboardDialogComponent
+ ]
+})
+export class DataExplorerV2Module {
+
+ constructor() {
+ }
+
+}
diff --git a/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.css b/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.css
new file mode 100644
index 0000000..e00a7b4
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.css
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ *
+ */
+
+.element-margin {
+ margin-top:10px;
+ margin-bottom:10px;
+}
+
+mat-toolbar {
+ background: #39b54a;
+ color:white;
+}
+
+mat-dialog-content {
+ padding: 24px;
+ -webkit-box-ordinal-group: 2;
+ -webkit-order: 1;
+ order: 1;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
+ flex-direction: column;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.mat-dialog-content {
+ width:100%;
+ height:74%;
+ margin: 0px;
+}
+
+.mat-dialog-actions {
+ margin-bottom:0px;
+ padding-right:10px;
+}
+
+.mat-radio-button {
+ padding: 10px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.html b/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.html
new file mode 100644
index 0000000..c746d86
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.html
@@ -0,0 +1,95 @@
+<!--
+~ 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.
+~
+-->
+
+<mat-toolbar>
+ <div class="md-toolbar-tools">
+ <h2>{{dialogTitle}}</h2>
+ <span fxFlex></span>
+ <button mat-icon-button (click)="onCancel()">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ </mat-toolbar>
+ <mat-divider></mat-divider>
+ <div mat-dialog-content class="md-dialog-content">
+ <div fxFlex="100">
+ <div fxFlex="100" style="margin:5px;width:100%">
+ <div *ngIf="page == 'select-pipeline'">
+ <h4>{{pages[0].description}}</h4>
+ <mat-grid-list
+ [cols]="3" [rowHeight]="200"
+ [gutterSize]="100">
+
+ <mat-grid-tile class="gray" *ngFor="let pipeline of visualizablePipelines">
+ <div [ngClass]="getSelectedPipelineCss(pipeline)"
+ (click)="selectPipeline(pipeline)">
+ {{iconText(pipeline.visualizationName)}}
+ <h5>{{pipeline.visualizationName}}</h5>
+ </div>
+ </mat-grid-tile>
+ </mat-grid-list>
+ </div>
+
+ <!-- Select Type -->
+ <div *ngIf="page == 'select-widget'" fxLayout="column">
+ <h4>{{pages[1].description}}</h4>
+ <mat-grid-list
+ [cols]="3" [rowHeight]="200"
+ [gutterSize]="100">
+
+ <mat-grid-tile class="gray" *ngFor="let widget of availableWidgets">
+ <div [ngClass]="getSelectedPipelineCss(widget.widgetLabel)"
+ (click)="selectWidget(widget)">
+ {{iconText(widget.widgetLabel)}}
+ <h5>{{widget.widgetLabel}}</h5>
+ </div>
+ </mat-grid-tile>
+ </mat-grid-list>
+ </div>
+
+ <!-- Select Scheme -->
+ <div *ngIf="page == 'configure-widget'" fxLayout="column">
+ <b><h4>{{pages[2].description}}</h4></b>
+ <div fxFlex="100" fxLayout="column">
+ <app-static-property *ngFor="let config of selectedWidget.config" [staticProperty]="config"
+ [staticProperties]="selectedWidget.config"
+ [eventSchema]="selectedPipeline.schema"></app-static-property>
+ </div>
+
+ </div>
+
+ </div>
+ </div>
+ </div>
+ <mat-divider></mat-divider>
+ <div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center">
+ <button mat-button mat-raised-button class="mat-basic" (click)="onCancel()">
+ Cancel
+ </button>
+ <button mat-button mat-raised-button class="mat-basic" (click)="back()" *ngIf="(!('select-pipeline'===page))
+ && !(data)">
+ Back
+ </button>
+ <button mat-button mat-raised-button color="primary" (click)="next()">
+ <span *ngIf="!data && 'configure-widget' === page">Create</span>
+ <span *ngIf="data && 'configure-widget' === page">Save</span>
+ <span *ngIf="data == null && !('configure-widget' === page)">Next</span>
+ </button>
+ </div>
+
+
diff --git a/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.ts b/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.ts
new file mode 100644
index 0000000..24df862
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/dialogs/add-widget/add-visualization-dialog.component.ts
@@ -0,0 +1,169 @@
+/*
+ * 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, Inject} from "@angular/core";
+import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
+import {DashboardService} from "../../services/dashboard.service";
+import {ElementIconText} from "../../../services/get-element-icon-text.service";
+import {WidgetRegistry} from "../../registry/widget-registry";
+import {MappingPropertyUnary} from "../../../connect/model/MappingPropertyUnary";
+import {MappingPropertyGenerator} from "../../sdk/matching/mapping-property-generator";
+import {EventProperty} from "../../../connect/schema-editor/model/EventProperty";
+import {EventSchema} from "../../../connect/schema-editor/model/EventSchema";
+import {DashboardWidget} from "../../../core-model/dashboard/DashboardWidget";
+import {DashboardWidgetSettings} from "../../../core-model/dashboard/DashboardWidgetSettings";
+import {VisualizablePipeline} from "../../../core-model/dashboard/VisualizablePipeline";
+import {Dashboard} from "../../models/dashboard.model";
+import {MappingPropertyNary} from "../../../connect/model/MappingPropertyNary";
+
+@Component({
+ selector: 'add-visualization-dialog-component',
+ templateUrl: './add-visualization-dialog.component.html',
+ styleUrls: ['./add-visualization-dialog.component.css']
+})
+export class AddVisualizationDialogComponent {
+
+ pages = [{
+ type: "select-pipeline",
+ title: "Select Pipeline",
+ description: "Select a pipeline you'd like to visualize"
+ }, {
+ type: "select-widget",
+ title: "Select Widget",
+ description: "Select widget"
+ }, {
+ type: "configure-widget",
+ title: "Configure Widget",
+ description: "Configure widget"
+ }];
+
+ visualizablePipelines: Array<VisualizablePipeline> = [];
+ availableWidgets: Array<DashboardWidgetSettings>;
+
+ selectedPipeline: VisualizablePipeline;
+ selectedWidget: DashboardWidgetSettings;
+
+ dashboard: Dashboard;
+
+ selectedType: any;
+ page: any = "select-pipeline";
+ dialogTitle: string;
+
+
+ constructor(
+ public dialogRef: MatDialogRef<AddVisualizationDialogComponent>,
+ @Inject(MAT_DIALOG_DATA) public data: any,
+ private dashboardService: DashboardService,
+ public elementIconText: ElementIconText) {
+ }
+
+ ngOnInit() {
+ if (!this.data) {
+ this.dialogTitle = "Add widget";
+ this.dashboardService.getVisualizablePipelines().subscribe(visualizations => {
+ this.visualizablePipelines = visualizations;
+ });
+ this.availableWidgets = WidgetRegistry.getAvailableWidgetTemplates();
+ } else {
+ this.dialogTitle = "Edit widget";
+ this.selectedPipeline = this.data.widget.dashboardWidgetDataConfig;
+ this.selectedWidget = this.data.widget.dashboardWidgetSettings;
+ this.page = 'configure-widget';
+ }
+ }
+
+ onCancel(): void {
+ this.dialogRef.close();
+ }
+
+ getSelectedPipelineCss(vis) {
+ return this.getSelectedCss(this.selectedPipeline, vis);
+ }
+
+ getSelectedVisTypeCss(type) {
+ return this.getSelectedCss(this.selectedType, type);
+ }
+
+ getSelectedCss(selected, current) {
+ if (selected == current) {
+ return "wizard-preview wizard-preview-selected";
+ } else {
+ return "wizard-preview";
+ }
+ }
+
+ getTabCss(page) {
+ if (page == this.page) return "md-fab md-accent";
+ else return "md-fab md-accent wizard-inactive";
+ }
+
+ selectPipeline(vis) {
+ this.selectedPipeline = vis;
+ this.next();
+ }
+
+ selectWidget(widget) {
+ this.selectedWidget = widget;
+ this.selectedWidget.config.forEach(sp => {
+ if (sp instanceof MappingPropertyUnary || sp instanceof MappingPropertyNary) {
+ let requirement: EventProperty = this.findRequirement(this.selectedWidget.requiredSchema, sp.internalName);
+ sp.mapsFromOptions = new MappingPropertyGenerator(requirement, this.selectedPipeline.schema.eventProperties).computeMatchingProperties();
+ }
+ });
+ this.next();
+ }
+
+ findRequirement(requiredSchema: EventSchema, internalName: string) {
+ return requiredSchema.eventProperties.find(ep => ep.runtimeName === internalName);
+ }
+
+ next() {
+ if (this.page == 'select-pipeline') {
+ this.page = 'select-widget';
+ } else if (this.page == 'select-widget') {
+ this.page = 'configure-widget';
+ } else {
+ let configuredWidget: DashboardWidget = new DashboardWidget();
+ configuredWidget.dashboardWidgetSettings = this.selectedWidget;
+ configuredWidget.dashboardWidgetDataConfig = this.selectedPipeline;
+ if (!this.data) {
+ this.dashboardService.saveWidget(configuredWidget).subscribe(response => {
+ this.dialogRef.close(response);
+ });
+ } else {
+ configuredWidget._id = this.data.widget._id;
+ configuredWidget._ref = this.data.widget._ref;
+ configuredWidget.widgetId = this.data.widget.widgetId;
+ this.dialogRef.close(configuredWidget);
+ }
+ }
+ }
+
+ back() {
+ if (this.page == 'select-widget') {
+ this.page = 'select-pipeline';
+ } else if (this.page == 'configure-widget') {
+ this.page = 'select-widget';
+ }
+ }
+
+ iconText(s) {
+ return this.elementIconText.getElementIconText(s);
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.css b/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.css
new file mode 100644
index 0000000..e00a7b4
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.css
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ *
+ */
+
+.element-margin {
+ margin-top:10px;
+ margin-bottom:10px;
+}
+
+mat-toolbar {
+ background: #39b54a;
+ color:white;
+}
+
+mat-dialog-content {
+ padding: 24px;
+ -webkit-box-ordinal-group: 2;
+ -webkit-order: 1;
+ order: 1;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
+ flex-direction: column;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.mat-dialog-content {
+ width:100%;
+ height:74%;
+ margin: 0px;
+}
+
+.mat-dialog-actions {
+ margin-bottom:0px;
+ padding-right:10px;
+}
+
+.mat-radio-button {
+ padding: 10px;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.html b/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.html
new file mode 100644
index 0000000..980b679
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.html
@@ -0,0 +1,55 @@
+<!--
+~ 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.
+~
+-->
+
+<mat-toolbar>
+ <div class="md-toolbar-tools">
+ <h2>{{createMode ? 'New dashboard' : 'Edit dashboard'}}</h2>
+ <span fxFlex></span>
+ <button mat-icon-button (click)="onCancel()">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+</mat-toolbar>
+<mat-divider></mat-divider>
+<div mat-dialog-content class="md-dialog-content">
+ <div fxFlex="100">
+ <div fxFlex="100" fxLayout="column" style="margin:5px;width:100%">
+ <mat-form-field class="full-width">
+ <mat-label>Dashboard Name</mat-label>
+ <input matInput [(ngModel)]="dashboard.name">
+ </mat-form-field>
+ <mat-form-field class="full-width">
+ <mat-label>Description</mat-label>
+ <input matInput [(ngModel)]="dashboard.description">
+ </mat-form-field>
+ <mat-checkbox [(ngModel)]="dashboard.displayHeader">Show name and description in dashboard</mat-checkbox>
+
+ </div>
+ </div>
+</div>
+<mat-divider></mat-divider>
+<div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center">
+ <button mat-button mat-raised-button class="mat-basic" (click)="onCancel()">
+ Cancel
+ </button>
+ <button mat-button mat-raised-button color="primary" (click)="onSave()">
+ {{createMode ? 'Create' : 'Save'}}
+ </button>
+</div>
+
+
diff --git a/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.ts b/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.ts
new file mode 100644
index 0000000..72d9433
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/dialogs/edit-dashboard/edit-dashboard-dialog.component.ts
@@ -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.
+ *
+ */
+
+import {Component, Inject} from "@angular/core";
+import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
+import {DashboardService} from "../../services/dashboard.service";
+import {DashboardWidgetSettings} from "../../../core-model/dashboard/DashboardWidgetSettings";
+import {VisualizablePipeline} from "../../../core-model/dashboard/VisualizablePipeline";
+import {Dashboard} from "../../models/dashboard.model";
+
+@Component({
+ selector: 'edit-dashboard-dialog-component',
+ templateUrl: './edit-dashboard-dialog.component.html',
+ styleUrls: ['./edit-dashboard-dialog.component.css']
+})
+export class EditDashboardDialogComponent {
+
+ createMode: boolean;
+ dashboard: Dashboard;
+
+ constructor(
+ public dialogRef: MatDialogRef<EditDashboardDialogComponent>,
+ private dashboardService: DashboardService) {
+ }
+
+ ngOnInit() {
+
+ }
+
+ onCancel(): void {
+ this.dialogRef.close();
+ }
+
+ onSave(): void {
+ if (this.createMode) {
+ this.dashboardService.saveDashboard(this.dashboard).subscribe();
+ } else {
+ this.dashboardService.updateDashboard(this.dashboard).subscribe();
+ }
+ this.dialogRef.close();
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/models/dashboard.model.ts b/ui/src/app/data-explorer-v2/models/dashboard.model.ts
new file mode 100644
index 0000000..1193e71
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/models/dashboard.model.ts
@@ -0,0 +1,36 @@
+/*
+ * 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 {GridsterConfig, GridsterItem} from "angular-gridster2";
+
+export interface DashboardConfig extends GridsterConfig {}
+
+export interface DashboardItem extends GridsterItem {
+ widgetId: string;
+ id: string;
+}
+
+export interface Dashboard {
+ id?: string;
+ name?: string;
+ description?: string;
+ displayHeader?: boolean;
+ widgets?: Array<DashboardItem>;
+ _id?: string;
+ _rev?: string;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/models/gridster-info.model.ts b/ui/src/app/data-explorer-v2/models/gridster-info.model.ts
new file mode 100644
index 0000000..43c41de
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/models/gridster-info.model.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 {GridsterItem, GridsterItemComponent} from "angular-gridster2";
+
+export interface GridsterInfo {
+ gridsterItem: GridsterItem;
+ gridsterItemComponent: GridsterItemComponent
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/models/multi-series.model.ts b/ui/src/app/data-explorer-v2/models/multi-series.model.ts
new file mode 100644
index 0000000..e95f777
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/models/multi-series.model.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 {DashboardItem} from "./dashboard.model";
+
+export interface MultiSeries {
+ name?: string;
+ series?: Array<MultiSeriesEntry>;
+}
+
+export interface MultiSeriesEntry {
+ name: string;
+ value: any;
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/registry/widget-config-builder.ts b/ui/src/app/data-explorer-v2/registry/widget-config-builder.ts
new file mode 100644
index 0000000..ed9a5f8
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/registry/widget-config-builder.ts
@@ -0,0 +1,121 @@
+/*
+ * 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 {FreeTextStaticProperty} from "../../connect/model/FreeTextStaticProperty";
+import {CollectedSchemaRequirements} from "../sdk/collected-schema-requirements";
+import {DashboardWidgetSettings} from "../../core-model/dashboard/DashboardWidgetSettings";
+import {Datatypes} from "../sdk/model/datatypes";
+import {ColorPickerStaticProperty} from "../../connect/model/ColorPickerStaticProperty";
+
+export class WidgetConfigBuilder {
+
+ static readonly BACKGROUND_COLOR_KEY: string = "spi-background-color-key";
+ static readonly PRIMARY_TEXT_COLOR_KEY: string = "spi-primary-text-color-key";
+ static readonly SECONDARY_TEXT_COLOR_KEY: string = "spi-secondary-text-color-key";
+
+ static readonly TITLE_KEY: string = "spi-title-key";
+
+ private widget: DashboardWidgetSettings;
+
+ private constructor(widgetName: string, widgetLabel: string, withColors?: boolean, withTitlePanel?: boolean) {
+ this.widget = new DashboardWidgetSettings();
+ this.widget.widgetLabel = widgetLabel;
+ this.widget.widgetName = widgetName;
+ this.widget.config = [];
+ if (withColors) {
+ this.requiredColorParameter(WidgetConfigBuilder.BACKGROUND_COLOR_KEY, "Background color", "The background" +
+ " color", "#1B1464");
+ this.requiredColorParameter(WidgetConfigBuilder.PRIMARY_TEXT_COLOR_KEY, "Primary text color", "The" +
+ " primary text color", "#FFFFFF");
+ this.requiredColorParameter(WidgetConfigBuilder.SECONDARY_TEXT_COLOR_KEY, "Secondary text color", "The" +
+ " secondary text" +
+ " color", "#bebebe")
+ }
+ if (withTitlePanel) {
+ this.requiredTextParameter(WidgetConfigBuilder.TITLE_KEY, "Title", "The title")
+ }
+ }
+
+ static create(widgetName: string, widgetLabel: string): WidgetConfigBuilder {
+ return new WidgetConfigBuilder(widgetName, widgetLabel);
+ }
+
+ static createWithSelectableColors(widgetName: string, widgetLabel: string): WidgetConfigBuilder {
+ return new WidgetConfigBuilder(widgetName, widgetLabel, true);
+ }
+
+ static createWithSelectableColorsAndTitlePanel(widgetName: string, widgetLabel: string): WidgetConfigBuilder {
+ return new WidgetConfigBuilder(widgetName, widgetLabel, true, true);
+ }
+
+ requiredTextParameter(id: string, label: string, description: string): WidgetConfigBuilder {
+ let fst: FreeTextStaticProperty = this.prepareStaticProperty(id, label, description, Datatypes.String.toUri())
+ this.widget.config.push(fst);
+ return this;
+ }
+
+ requiredColorParameter(id: string, label: string, description: string, defaultColor?: string): WidgetConfigBuilder {
+ let csp = new ColorPickerStaticProperty();
+ csp.internalName = id;
+ csp.label = label;
+ csp.description = description;
+ if (defaultColor) {
+ csp.selectedColor = defaultColor;
+ }
+ this.widget.config.push(csp);
+ return this;
+ }
+
+
+ requiredIntegerParameter(id: string, label: string, description: string): WidgetConfigBuilder {
+ let fst: FreeTextStaticProperty = this.prepareStaticProperty(id, label, description, Datatypes.Integer.toUri())
+ this.widget.config.push(fst);
+ return this;
+ }
+
+ requiredFloatParameter(id: string, label: string, description: string): WidgetConfigBuilder {
+ let fst: FreeTextStaticProperty = this.prepareStaticProperty(id, label, description, Datatypes.Float.toUri())
+ this.widget.config.push(fst);
+ return this;
+ }
+
+ requiredSchema(collectedSchemaRequirements: CollectedSchemaRequirements): WidgetConfigBuilder {
+ this.widget.requiredSchema = collectedSchemaRequirements.getEventSchema();
+ this.widget.config = this.widget.config.concat(collectedSchemaRequirements.getRequiredMappingProperties());
+
+ return this;
+ }
+
+ prepareStaticProperty(id: string, label: string, description: string, datatype: string) {
+ let fst: FreeTextStaticProperty = new FreeTextStaticProperty();
+ fst.internalName = id;
+ fst.label = label;
+ fst.description = description;
+ fst.requiredDatatype = datatype;
+
+ return fst;
+ }
+
+ build(): DashboardWidgetSettings {
+ for(let i = 0; i < this.widget.config.length; i++) {
+ this.widget.config[i].index = i;
+ }
+ return this.widget;
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/registry/widget-registry.ts b/ui/src/app/data-explorer-v2/registry/widget-registry.ts
new file mode 100644
index 0000000..3c62fe6
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/registry/widget-registry.ts
@@ -0,0 +1,44 @@
+/*
+ * 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 {NumberConfig} from "../components/widgets/number/number-config";
+import {DashboardWidgetSettings} from "../../core-model/dashboard/DashboardWidgetSettings";
+import {WidgetConfig} from "../components/widgets/base/base-config";
+import {LineConfig} from "../components/widgets/line/line-config";
+import {TableConfig} from "../components/widgets/table/table-config";
+import {GaugeConfig} from "../components/widgets/gauge/gauge-config";
+import {ImageConfig} from "../components/widgets/image/image-config";
+import {AreaConfig} from "../components/widgets/area/area-config";
+
+export class WidgetRegistry {
+
+ private static availableWidgets: Array<WidgetConfig> = [
+ new NumberConfig(),
+ new LineConfig(),
+ new TableConfig(),
+ new GaugeConfig(),
+ new ImageConfig(),
+ new AreaConfig()
+ ];
+
+ static getAvailableWidgetTemplates(): Array<DashboardWidgetSettings> {
+ let widgetTemplates = new Array<DashboardWidgetSettings>();
+ this.availableWidgets.forEach(widget => widgetTemplates.push(widget.getConfig()));
+ return widgetTemplates;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/collected-schema-requirements.ts b/ui/src/app/data-explorer-v2/sdk/collected-schema-requirements.ts
new file mode 100644
index 0000000..da96d05
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/collected-schema-requirements.ts
@@ -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.
+ *
+ */
+
+import {StaticProperty} from "../../connect/model/StaticProperty";
+import {EventProperty} from "../../connect/schema-editor/model/EventProperty";
+import {EventSchema} from "../../connect/schema-editor/model/EventSchema";
+
+export class CollectedSchemaRequirements {
+
+ constructor(private requiredEventProperties: Array<EventProperty>, private requiredMappingProperties: Array<StaticProperty>) {
+
+ }
+
+ getEventSchema(): EventSchema {
+ let eventSchema = new EventSchema();
+ eventSchema.eventProperties = this.requiredEventProperties;
+ return eventSchema;
+ }
+
+ getRequiredMappingProperties(): Array<StaticProperty> {
+ return this.requiredMappingProperties;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/ep-requirements.ts b/ui/src/app/data-explorer-v2/sdk/ep-requirements.ts
new file mode 100644
index 0000000..b298a7a
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/ep-requirements.ts
@@ -0,0 +1,68 @@
+/*
+ * 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 {EventProperty} from "../../connect/schema-editor/model/EventProperty";
+import {EventPropertyPrimitive} from "../../connect/schema-editor/model/EventPropertyPrimitive";
+import {Datatypes} from "./model/datatypes";
+
+export class EpRequirements {
+
+ private static ep(): EventPropertyPrimitive {
+ let ep = new EventPropertyPrimitive(undefined, undefined);
+ return ep;
+ }
+
+ static anyProperty(): EventProperty {
+ return EpRequirements.ep();
+ }
+
+ static imageReq(): EventProperty {
+ return EpRequirements.domainPropertyReq("https://image.com");
+ }
+
+ static timestampReq(): EventProperty {
+ return EpRequirements.domainPropertyReq("http://schema.org/DateTime");
+ }
+
+ static numberReq(): EventProperty {
+ return EpRequirements.datatypeReq(Datatypes.Number);
+ }
+
+ static stringReq(): EventProperty {
+ return EpRequirements.datatypeReq(Datatypes.String);
+ }
+
+ static integerReq(): EventProperty {
+ return EpRequirements.datatypeReq(Datatypes.Integer);
+ }
+
+ static domainPropertyReq(domainProperty: string): EventPropertyPrimitive {
+ let eventProperty = EpRequirements.ep();
+ eventProperty.setDomainProperty(domainProperty);
+ return eventProperty;
+
+ }
+
+ static datatypeReq(datatype: Datatypes): EventPropertyPrimitive {
+ let eventProperty = EpRequirements.ep();
+ eventProperty.setRuntimeType(datatype.toUri());
+ return eventProperty;
+}
+
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/extractor/static-property-extractor.ts b/ui/src/app/data-explorer-v2/sdk/extractor/static-property-extractor.ts
new file mode 100644
index 0000000..93d0adb
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/extractor/static-property-extractor.ts
@@ -0,0 +1,78 @@
+/*
+ * 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 {EventSchema} from "../../../connect/schema-editor/model/EventSchema";
+import {StaticProperty} from "../../../connect/model/StaticProperty";
+import {MappingPropertyUnary} from "../../../connect/model/MappingPropertyUnary";
+import {FreeTextStaticProperty} from "../../../connect/model/FreeTextStaticProperty";
+import {ColorPickerStaticProperty} from "../../../connect/model/ColorPickerStaticProperty";
+import {MappingPropertyNary} from "../../../connect/model/MappingPropertyNary";
+
+export class StaticPropertyExtractor {
+
+ constructor(private inputSchema: EventSchema,
+ private staticProperties: Array<StaticProperty>) {
+
+ }
+
+ hasStaticProperty(internalId: string): boolean {
+ return this.getStaticPropertyByName(internalId) !== undefined;
+ }
+
+ mappingPropertyValue(internalId: string): string {
+ let sp: MappingPropertyUnary = this.getStaticPropertyByName(internalId) as MappingPropertyUnary;
+ return this.removePrefix(sp.selectedProperty);
+ }
+
+ mappingPropertyValues(internalId: string): Array<string> {
+ let sp: MappingPropertyNary = this.getStaticPropertyByName(internalId) as MappingPropertyNary;
+ let properties: Array<string> = [];
+ sp.selectedProperties.forEach(ep => {
+ properties.push(this.removePrefix(ep));
+ });
+ return properties;
+ }
+
+ singleValueParameter(internalId: string): any {
+ let sp: FreeTextStaticProperty = this.getStaticPropertyByName(internalId) as FreeTextStaticProperty;
+ return sp.value;
+ }
+
+ selectedColor(internalId: string): any {
+ let sp: ColorPickerStaticProperty = this.getStaticPropertyByName(internalId) as ColorPickerStaticProperty;
+ return sp.selectedColor;
+ }
+
+ stringParameter(internalId: string): string {
+ return this.singleValueParameter(internalId) as string;
+ }
+
+ integerParameter(internalId: string): number {
+ return this.singleValueParameter(internalId) as number;
+ }
+
+ getStaticPropertyByName(internalId: string): StaticProperty {
+ return this.staticProperties.find(sp => (sp.internalName == internalId));
+ }
+
+
+ removePrefix(propertyValue: string) {
+ return propertyValue.split("::").length > 1 ? propertyValue.split("::")[1] : propertyValue;
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/matching/datatype-match.ts b/ui/src/app/data-explorer-v2/sdk/matching/datatype-match.ts
new file mode 100644
index 0000000..5b71398
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/matching/datatype-match.ts
@@ -0,0 +1,44 @@
+/*
+ * 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 {Datatypes} from "../model/datatypes";
+
+export class DatatypeMatch {
+
+ match(datatypeRequirement: string, datatypeOffer: string) {
+ if (datatypeRequirement == undefined) {
+ return true;
+ } else {
+ return (datatypeRequirement == datatypeOffer) || this.subClassOf(datatypeOffer, datatypeRequirement);
+ }
+ }
+
+ subClassOf(offer: string, requirement: string): boolean {
+ if (!(requirement === (Datatypes.Number.toUri()))){
+ return false;
+ }
+ else {
+ if (offer === Datatypes.Integer.toUri()
+ || offer === Datatypes.Long.toUri()
+ || offer === Datatypes.Double.toUri()
+ || offer === Datatypes.Float.toUri())
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/matching/domain-property-match.ts b/ui/src/app/data-explorer-v2/sdk/matching/domain-property-match.ts
new file mode 100644
index 0000000..836df01
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/matching/domain-property-match.ts
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ */
+
+export class DomainPropertyMatch {
+
+ match(domainPropertyRequirement: string, domainPropertyOffer: string) {
+ if (domainPropertyRequirement == undefined) {
+ return true;
+ } else {
+ return domainPropertyRequirement == domainPropertyOffer;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/matching/mapping-property-generator.ts b/ui/src/app/data-explorer-v2/sdk/matching/mapping-property-generator.ts
new file mode 100644
index 0000000..3f47e1c
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/matching/mapping-property-generator.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 {EventProperty} from "../../../connect/schema-editor/model/EventProperty";
+import {PropertyMatch} from "./property-match";
+
+export class MappingPropertyGenerator {
+
+ private selector: string = "s0";
+ private separator: string = "::";
+
+ constructor(private requiredEventProperty: EventProperty, private providedEventProperties: Array<EventProperty>) {
+
+ }
+
+ computeMatchingProperties(): Array<string> {
+ let mapsFromOptions: Array<string> = [];
+
+ this.providedEventProperties.forEach(ep => {
+ if (new PropertyMatch().match(this.requiredEventProperty, ep)) {
+ mapsFromOptions.push(this.makeSelector(ep.runtimeName));
+ }
+ });
+
+ return mapsFromOptions;
+ }
+
+ makeSelector(runtimeName: string): string {
+ return this.selector + this.separator + runtimeName;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/matching/primitive-property-match.ts b/ui/src/app/data-explorer-v2/sdk/matching/primitive-property-match.ts
new file mode 100644
index 0000000..6fadf06
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/matching/primitive-property-match.ts
@@ -0,0 +1,33 @@
+/*
+ * 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 {EventPropertyPrimitive} from "../../../connect/schema-editor/model/EventPropertyPrimitive";
+import {DatatypeMatch} from "./datatype-match";
+import {DomainPropertyMatch} from "./domain-property-match";
+
+export class PrimitivePropertyMatch {
+
+ match(requirement: EventPropertyPrimitive, offer: EventPropertyPrimitive) {
+ if (requirement != undefined) {
+ return new DatatypeMatch().match(requirement.runtimeType, offer.runtimeType) &&
+ new DomainPropertyMatch().match(requirement.domainProperty, offer.domainProperty);
+ } else {
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/matching/property-match.ts b/ui/src/app/data-explorer-v2/sdk/matching/property-match.ts
new file mode 100644
index 0000000..29e145c
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/matching/property-match.ts
@@ -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.
+ *
+ */
+
+import {EventProperty} from "../../../connect/schema-editor/model/EventProperty";
+import {EventPropertyPrimitive} from "../../../connect/schema-editor/model/EventPropertyPrimitive";
+import {PrimitivePropertyMatch} from "./primitive-property-match";
+
+export class PropertyMatch {
+
+ match(requirement: EventProperty, offer: EventProperty): boolean {
+ if (requirement instanceof EventPropertyPrimitive && offer instanceof EventPropertyPrimitive) {
+ return new PrimitivePropertyMatch().match(requirement, offer);
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/model/datatypes.ts b/ui/src/app/data-explorer-v2/sdk/model/datatypes.ts
new file mode 100644
index 0000000..a990e63
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/model/datatypes.ts
@@ -0,0 +1,40 @@
+/*
+ * 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 {Vocabulary} from "./vocabulary";
+
+export class Datatypes {
+
+ static readonly Integer = new Datatypes(Vocabulary.XSD, "integer");
+ static readonly Long = new Datatypes(Vocabulary.XSD, "long");
+ static readonly Float = new Datatypes(Vocabulary.XSD, "float");
+ static readonly Boolean = new Datatypes(Vocabulary.XSD, "boolean");
+ static readonly String = new Datatypes(Vocabulary.XSD, "string");
+ static readonly Double = new Datatypes(Vocabulary.XSD, "double");
+ static readonly Number = new Datatypes(Vocabulary.SO, "Number");
+
+ private constructor(private readonly vocabulary: string, private readonly entity: string ) {
+
+ }
+
+ toUri() {
+ return this.vocabulary + this.entity;
+ }
+
+
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/model/vocabulary.ts b/ui/src/app/data-explorer-v2/sdk/model/vocabulary.ts
new file mode 100644
index 0000000..175377b
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/model/vocabulary.ts
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ *
+ */
+
+export class Vocabulary {
+
+ static readonly XSD: string = "http://www.w3.org/2001/XMLSchema#";
+ static readonly SO: string = "http://schema.org/";
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/sdk/schema-requirements-builder.ts b/ui/src/app/data-explorer-v2/sdk/schema-requirements-builder.ts
new file mode 100644
index 0000000..ad0c14e
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/sdk/schema-requirements-builder.ts
@@ -0,0 +1,69 @@
+/*
+ * 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 {EventProperty} from "../../connect/schema-editor/model/EventProperty";
+import {StaticProperty} from "../../connect/model/StaticProperty";
+import {CollectedSchemaRequirements} from "./collected-schema-requirements";
+import {MappingPropertyUnary} from "../../connect/model/MappingPropertyUnary";
+import {MappingPropertyNary} from "../../connect/model/MappingPropertyNary";
+
+export class SchemaRequirementsBuilder {
+
+ private requiredEventProperties: Array<EventProperty>;
+ private staticProperties: Array<StaticProperty>;
+
+ private constructor() {
+ this.requiredEventProperties = [];
+ this.staticProperties = [];
+ }
+
+ static create(): SchemaRequirementsBuilder {
+ return new SchemaRequirementsBuilder();
+ }
+
+ requiredPropertyWithUnaryMapping(internalId: string, label: string, description: string, eventProperty: EventProperty): SchemaRequirementsBuilder {
+ eventProperty.setRuntimeName(internalId);
+ let mp = this.makeMappingProperty(internalId, label, description, new MappingPropertyUnary());
+
+ this.staticProperties.push(mp);
+ this.requiredEventProperties.push(eventProperty);
+
+ return this;
+ }
+
+ requiredPropertyWithNaryMapping(internalId: string, label: string, description: string, eventProperty: EventProperty): SchemaRequirementsBuilder {
+ eventProperty.setRuntimeName(internalId);
+ let mp = this.makeMappingProperty(internalId, label, description, new MappingPropertyNary());
+
+ this.staticProperties.push(mp);
+ this.requiredEventProperties.push(eventProperty);
+
+ return this;
+ }
+
+ makeMappingProperty(internalId: string, label: string, description: string, sp: StaticProperty): StaticProperty {
+ sp.internalName = internalId;
+ sp.label = label;
+ sp.description = description;
+ return sp;
+ }
+
+ build() {
+ return new CollectedSchemaRequirements(this.requiredEventProperties, this.staticProperties);
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/services/dashboard.service.ts b/ui/src/app/data-explorer-v2/services/dashboard.service.ts
new file mode 100644
index 0000000..2f97107
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/services/dashboard.service.ts
@@ -0,0 +1,137 @@
+/*
+ * 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 {HttpClient, HttpHeaders} from "@angular/common/http";
+import {Injectable} from "@angular/core";
+import {map} from "rxjs/operators";
+import {from, Observable} from "rxjs";
+import {AuthStatusService} from "../../services/auth-status.service";
+import {Dashboard} from "../models/dashboard.model";
+import {EventSchema} from "../../connect/schema-editor/model/EventSchema";
+import {EventProperty} from "../../connect/schema-editor/model/EventProperty";
+import {EventPropertyPrimitive} from "../../connect/schema-editor/model/EventPropertyPrimitive";
+import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
+import {StatusMessage} from "../../connect/model/message/StatusMessage";
+import {RuntimeOptionsResponse} from "../../connect/model/connect/runtime/RuntimeOptionsResponse";
+import {DashboardWidget} from "../../core-model/dashboard/DashboardWidget";
+import {VisualizablePipeline} from "../../core-model/dashboard/VisualizablePipeline";
+
+@Injectable()
+export class DashboardService {
+
+
+ constructor(private http: HttpClient,
+ private authStatusService: AuthStatusService,
+ private tsonLdSerializerService: TsonLdSerializerService,) {
+ }
+
+ getVisualizablePipelines(): Observable<Array<VisualizablePipeline>> {
+ return this.http
+ .get(this.visualizablePipelineUrl)
+ .map(data => {
+ return this.tsonLdSerializerService.fromJsonLdContainer(data, 'sp:VisualizablePipeline')
+ });
+ }
+
+ getDashboards(): Observable<Array<Dashboard>> {
+ return this.http.get(this.dashboardUrl).map(data => {
+ return data as Dashboard[];
+ });
+ }
+
+ updateDashboard(dashboard: Dashboard): Observable<Dashboard> {
+ return this.http.put(this.dashboardUrl + "/" +dashboard._id, dashboard).map(data => {
+ return data as Dashboard;
+ });
+ }
+
+ deleteDashboard(dashboard: Dashboard): Observable<any> {
+ return this.http.delete(this.dashboardUrl + "/" +dashboard._id);
+ }
+
+ saveDashboard(dashboard: Dashboard): Observable<any> {
+ return this.http.post(this.dashboardUrl, dashboard);
+ }
+
+ private get baseUrl() {
+ return '/streampipes-backend';
+ }
+
+ private get dashboardUrl() {
+ return this.baseUrl + '/api/v2/users/' + this.authStatusService.email + '/ld/dashboards'
+ }
+
+ private get dashboardWidgetUrl() {
+ return this.baseUrl + '/api/v2/users/' + this.authStatusService.email + '/ld/widgets'
+ }
+
+ private get visualizablePipelineUrl() {
+ return this.baseUrl + '/api/v2/users/' + this.authStatusService.email + '/ld/pipelines'
+ }
+
+ getWidget(widgetId: string): Observable<DashboardWidget> {
+ let promise = new Promise<DashboardWidget>((resolve, reject) => {
+ this.http.get(this.dashboardWidgetUrl + "/" +widgetId).subscribe(response => {
+ let dashboardWidget: DashboardWidget = this.tsonLdSerializerService.fromJsonLd(response, "sp:DashboardWidgetModel");
+ dashboardWidget.dashboardWidgetSettings.config.sort((a, b) => {
+ return a.index - b.index;
+ });
+ resolve(dashboardWidget);
+ });
+ });
+ return from(promise);
+ }
+
+ saveWidget(widget: DashboardWidget): Observable<DashboardWidget> {
+ return this.serializeAndPost(this.dashboardWidgetUrl, widget);
+ }
+
+ deleteWidget(widgetId: string): Observable<any> {
+ return this.http.delete(this.dashboardWidgetUrl + "/" +widgetId);
+ }
+
+ updateWidget(widget: DashboardWidget): Observable<any> {
+ let promise = new Promise<DashboardWidget>((resolve, reject) => {
+ this.tsonLdSerializerService.toJsonLd(widget).subscribe(serialized => {
+ this.http.put(this.dashboardWidgetUrl + "/" +widget._id, serialized, this.jsonLdHeaders()).subscribe(result => {
+ resolve();
+ })
+ });
+ });
+ return from(promise);
+ }
+
+ serializeAndPost(url: string, object: any): Observable<DashboardWidget> {
+ let promise = new Promise<DashboardWidget>((resolve, reject) => {
+ this.tsonLdSerializerService.toJsonLd(object).subscribe(serialized => {
+ this.http.post(url, serialized, this.jsonLdHeaders()).pipe(map(response => {
+ resolve(this.tsonLdSerializerService.fromJsonLd(response, "sp:DashboardWidgetModel"));
+ })).subscribe();
+ });
+ });
+ return from(promise);
+ }
+
+ jsonLdHeaders(): any {
+ return {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/ld+json',
+ }),
+ };
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/services/refresh-dashboard.service.ts b/ui/src/app/data-explorer-v2/services/refresh-dashboard.service.ts
new file mode 100644
index 0000000..4f9c0e3
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/services/refresh-dashboard.service.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 {Injectable} from "@angular/core";
+import {ReplaySubject} from "rxjs";
+
+@Injectable()
+export class RefreshDashboardService {
+
+ public refreshSubject: ReplaySubject<string> = new ReplaySubject<string>();
+
+ public notify(currentDashboard: string): void {
+ this.refreshSubject.next(currentDashboard);
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/services/resize.service.ts b/ui/src/app/data-explorer-v2/services/resize.service.ts
new file mode 100644
index 0000000..9c53041
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/services/resize.service.ts
@@ -0,0 +1,31 @@
+/*
+ * 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 {ReplaySubject} from "rxjs";
+import {Injectable} from "@angular/core";
+import {GridsterInfo} from "../models/gridster-info.model";
+
+@Injectable()
+export class ResizeService {
+
+ public resizeSubject: ReplaySubject<GridsterInfo> = new ReplaySubject<GridsterInfo>();
+
+ public notify(info: GridsterInfo): void {
+ this.resizeSubject.next(info);
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/services/websocket.config.ts b/ui/src/app/data-explorer-v2/services/websocket.config.ts
new file mode 100644
index 0000000..d58c891
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/services/websocket.config.ts
@@ -0,0 +1,36 @@
+/*
+ * 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 {InjectableRxStompConfig} from "@stomp/ng2-stompjs";
+import {WebsocketSettings} from "./websocket.settings";
+
+export const streamPipesStompConfig: InjectableRxStompConfig = {
+
+ brokerURL: new WebsocketSettings().getBrokerUrl(),
+
+ connectHeaders: {
+ login: 'admin',
+ passcode: 'admin'
+ },
+
+ heartbeatIncoming: 0,
+ heartbeatOutgoing: 20000,
+
+ reconnectDelay: 200,
+
+};
\ No newline at end of file
diff --git a/ui/src/app/data-explorer-v2/services/websocket.settings.ts b/ui/src/app/data-explorer-v2/services/websocket.settings.ts
new file mode 100644
index 0000000..9503872
--- /dev/null
+++ b/ui/src/app/data-explorer-v2/services/websocket.settings.ts
@@ -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.
+ *
+ */
+
+export class WebsocketSettings {
+
+ getBrokerUrl(): string {
+ return this.getWebsocketScheme() + "//" + location.host + "/streampipes/ws";
+ }
+
+ getWebsocketScheme(): string {
+ if (location.protocol === 'https:') {
+ return "wss:";
+ } else {
+ return "ws:";
+ }
+ }
+}
\ No newline at end of file