This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch 2990-improve-home-screen-status-widgets
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to
refs/heads/2990-improve-home-screen-status-widgets by this push:
new 849a243632 feat(#2990): Improve status widgets on home screen
849a243632 is described below
commit 849a2436320c8d2b01b54b84563f37e8334af1ce
Author: Dominik Riemer <[email protected]>
AuthorDate: Tue Jul 2 13:01:50 2024 +0200
feat(#2990): Improve status widgets on home screen
---
ui/deployment/home.service.mst | 34 ++++++++--
ui/deployment/modules.yml | 62 +++++++++++------
ui/deployment/prebuild.js | 3 +-
ui/src/app/home/components/status.component.html | 79 ++++++++++------------
ui/src/app/home/components/status.component.scss | 42 ++++++------
ui/src/app/home/components/status.component.ts | 59 ++++++++++------
ui/src/app/home/home.component.html | 30 ++++----
ui/src/app/home/home.component.ts | 10 ++-
ui/src/app/home/home.module.ts | 2 +
.../status.component.scss => models/home.model.ts} | 68 ++++++++-----------
10 files changed, 218 insertions(+), 171 deletions(-)
diff --git a/ui/deployment/home.service.mst b/ui/deployment/home.service.mst
index f22b25a772..9a6a6de7a9 100644
--- a/ui/deployment/home.service.mst
+++ b/ui/deployment/home.service.mst
@@ -19,42 +19,66 @@
import { Injectable } from '@angular/core';
import { PageName } from '../_enums/page-name.enum';
import { AuthService } from '../services/auth.service';
+import { ServiceLink } from './models/home.model';
+import {
+ AdapterService,
+ DashboardService,
+ DataViewDataExplorerService, PipelineElementService,
+ PipelineService
+} from '@streampipes/platform-services';
+import { UserRole } from '../_enums/user-role.enum';
@Injectable({providedIn: 'root'})
export class HomeService {
- constructor(private authService: AuthService) {
+ constructor(private authService: AuthService,
+ private adapterService: AdapterService,
+ private dashboardService: DashboardService,
+ private dataViewService: DataViewDataExplorerService,
+ private pipelineService: PipelineService,
+ private pipelineElementService: PipelineElementService) {
}
getFilteredServiceLinks() {
return this.getServiceLinks().filter(s =>
this.authService.isAnyAccessGranted(s.pageNames));
}
- getServiceLinks() {
+ getServiceLinks(): ServiceLink[] {
return [
{{#modulesActive}}
{
name: "{{title}}",
description: "{{description}}",
- imageUrl: "{{{homeImage}}}",
icon: "{{{icon}}}",
pageNames: [{{{pageNames}}}],
link: {
newWindow: false,
value: "{{{link}}}"
+ },
+ showStatusBox: {{{showStatusBox}}}{{#statusBox}},
+ statusBox: {
+ link: {{{statusBox.link}}},
+ createLink: {{{statusBox.createLinks}}},
+ createTitle: '{{{statusBox.createTitle}}}',
+ title: '{{{statusBox.title}}}',
+ dataFns: {{{statusBox.dataFns}}},
+ viewRoles: {{{statusBox.viewRoles}}},
+ createRoles: {{{statusBox.createRoles}}},
+ icon: '{{{icon}}}'
}
+ {{/statusBox}}
},
{{/modulesActive}}
{
name: "Notifications",
description: "The notification module lets you view all
notifications generated by pipelines.",
- imageUrl: "assets/img/home/notifications.png",
icon: "chat",
pageNames: [PageName.NOTIFICATIONS],
link: {
newWindow: false,
value: "notifications"
- }
+ },
+ showStatusBox: false
}
];
}
diff --git a/ui/deployment/modules.yml b/ui/deployment/modules.yml
index 0250c7c8d6..364d8aa77d 100644
--- a/ui/deployment/modules.yml
+++ b/ui/deployment/modules.yml
@@ -24,23 +24,9 @@ spAssets:
title: 'Asset Management'
description: 'Manage assets which help assigning pipelines, dashboards and
adapters to real-world objects such as machines and plants.'
icon: 'precision_manufacturing'
- homeImage: ''
admin: true
pageNames: 'PageName.ASSETS'
-spEditor:
- componentImport: True
- ng5_moduleName: 'EditorModule'
- ng5_component: 'EditorComponent'
- ng5_componentPath: './editor/editor.component'
- path: './editor/editor.module'
- link: 'editor'
- url: '/editor/:pipeline'
- title: 'Pipeline Editor'
- description: 'The pipeline editor lets you create flexible data pipelines
based on installed data streams, data processors, and data sinks.'
- icon: 'dashboard'
- homeImage: '/assets/img/home/editor.png'
- admin: false
- pageNames: 'PageName.PIPELINE_EDITOR'
+ showStatusBox: false
spConnect:
componentImport: False
ng5_moduleName: 'ConnectModule'
@@ -52,9 +38,17 @@ spConnect:
title: 'Connect'
description: 'StreamPipes Connect lets you easily connect new data sources
for a variety of data formats and protocols.'
icon: 'power'
- homeImage: '/assets/img/home/editor.png'
admin: False
pageNames: 'PageName.CONNECT'
+ showStatusBox: true
+ statusBox:
+ link: "['connect']"
+ createLinks: "['connect', 'create']"
+ title: 'Adapters'
+ createTitle: 'New adapter'
+ dataFns: '[this.adapterService.getAdapters()]'
+ viewRoles: '[UserRole.ROLE_CONNECT_ADMIN]'
+ createRoles: '[UserRole.ROLE_CONNECT_ADMIN]'
spPipelines:
componentImport: False
ng5_moduleName: 'PipelinesModule'
@@ -66,9 +60,17 @@ spPipelines:
title: 'Pipelines'
description: 'All created pipelines are available in the pipeline view,
where you can also start and stop pipelines.'
icon: 'play_arrow'
- homeImage: '/assets/img/home/pipelines.png'
admin: False
pageNames: 'PageName.PIPELINE_OVERVIEW'
+ showStatusBox: true
+ statusBox:
+ link: "['pipelines']"
+ createLinks: "['pipelines', 'create']"
+ title: 'Pipelines'
+ createTitle: 'New pipeline'
+ dataFns: '[this.pipelineService.getPipelines()]'
+ viewRoles: '[UserRole.ROLE_PIPELINE_ADMIN,
UserRole.ROLE_PIPELINE_USER]'
+ createRoles: '[UserRole.ROLE_PIPELINE_ADMIN]'
spConfiguration:
componentImport: False
ng5_moduleName: 'ConfigurationModule'
@@ -80,9 +82,9 @@ spConfiguration:
title: 'Configuration'
description: 'In the configuration module, basic StreamPipes settings and
services can be configured.'
icon: 'settings'
- homeImage: '/assets/img/home/configuration.png'
pageNames: 'PageName.SETTINGS'
admin: True
+ showStatusBox: false
spAppOverview:
componentImport: False
ng5_moduleName: 'AppOverviewModule'
@@ -94,9 +96,9 @@ spAppOverview:
title: 'Apps'
description: 'The app overview lets you access additional plugins.'
icon: 'apps'
- homeImage: '/assets/img/home/configuration.png'
admin: false
pageNames: 'PageName.APPS'
+ showStatusBox: false
spDashboard:
componentImport: False
ng5_moduleName: 'DashboardModule'
@@ -108,9 +110,17 @@ spDashboard:
title: 'Dashboard'
description: 'The live dashboard visualizes data in real-time.'
icon: 'insert_chart'
- homeImage: '/assets/img/home/configuration.png'
admin: false
pageNames: 'PageName.DASHBOARD'
+ showStatusBox: true
+ statusBox:
+ link: "['dashboard']"
+ createLinks: "['dashboard']"
+ title: 'Dashboards'
+ createTitle: 'New dashboard'
+ dataFns: '[this.dashboardService.getDashboards()]'
+ viewRoles: '[UserRole.ROLE_DASHBOARD_ADMIN,
UserRole.ROLE_DASHBOARD_USER]'
+ createRoles: '[UserRole.ROLE_DASHBOARD_ADMIN]'
spDataExplorer:
componentImport: False
ng5_moduleName: 'DataExplorerModule'
@@ -122,9 +132,17 @@ spDataExplorer:
title: 'Data Explorer'
description: 'The data explorer lets you visually inspect historical data
from your connected sources.'
icon: 'search'
- homeImage: '/assets/img/home/configuration.png'
admin: false
pageNames: 'PageName.DATA_EXPLORER'
+ showStatusBox: true
+ statusBox:
+ link: "['dataexplorer']"
+ createLinks: "['dataexplorer']"
+ title: 'Data Views'
+ createTitle: 'New data view'
+ dataFns: '[this.dataViewService.getDataViews()]'
+ viewRoles: '[UserRole.ROLE_DATA_EXPLORER_ADMIN,
UserRole.ROLE_DATA_EXPLORER_USER]'
+ createRoles: '[UserRole.ROLE_DATA_EXPLORER_ADMIN]'
spFiles:
componentImport: False
ng5_moduleName: 'FilesModule'
@@ -136,6 +154,6 @@ spFiles:
title: 'File Management'
description: 'The file management module lets you upload and manage files
that are used by adapters or pipeline elements.'
icon: 'folder'
- homeImage: '/assets/img/home/configuration.png'
admin: true
pageNames: 'PageName.FILE_UPLOAD'
+ showStatusBox: false
diff --git a/ui/deployment/prebuild.js b/ui/deployment/prebuild.js
index 460ecd1624..d4628ea5ba 100644
--- a/ui/deployment/prebuild.js
+++ b/ui/deployment/prebuild.js
@@ -79,7 +79,8 @@ for (let module of config.modules) {
icon: modules[module]['icon'],
admin: modules[module]['admin'],
description: modules[module]['description'],
- homeImage: modules[module]['homeImage'],
+ showStatusBox: modules[module]['showStatusBox'],
+ statusBox: modules[module]['statusBox'],
});
console.log('Active Angular Module: ' + module);
}
diff --git a/ui/src/app/home/components/status.component.html
b/ui/src/app/home/components/status.component.html
index 2ccda56988..6a7f46bd1f 100644
--- a/ui/src/app/home/components/status.component.html
+++ b/ui/src/app/home/components/status.component.html
@@ -16,53 +16,44 @@
~
-->
-<div fxFlex="100" fxLayout="row">
- <div
- fxFlex="25"
- class="status-container pipelines mr-20"
- (click)="navigate('pipelines')"
- >
- <div fxFill="100" fxLayout="column" fxLayoutAlign="center center">
- <div class="status-container-number" fxLayoutAlign="start center">
- {{ availablePipelines }}
+<div
+ fxFlex="100"
+ class="status-container p-10"
+ (click)="navigate(statusBox.link)"
+>
+ <div fxLayout="row" fxFlex="100">
+ <div fxFlex fxLayout="column" fxLayoutAlign="start start">
+ <div fxFlex fxLayout="column">
+ <div class="status-container-number">
+ <span>{{ resourceCount }}</span>
+ </div>
+ <div
+ class="status-container-text"
+ fxFlex
+ fxLayoutAlign="end end"
+ >
+ <span>{{ statusBox.title }}</span>
+ </div>
</div>
- <div class="status-container-text">pipelines created</div>
- </div>
- </div>
- <div
- fxFlex="25"
- class="status-container pipelines-running mr-20"
- (click)="navigate('pipelines')"
- >
- <div fxFill="100" fxLayout="column" fxLayoutAlign="center center">
- <div class="status-container-number" fxLayoutAlign="start center">
- {{ runningPipelines }}
+ <div fxFlex="100" fxLayoutAlign="end end" class="w-100">
+ <div
+ fxFlex="100"
+ fxLayoutAlign="start center"
+ *ngIf="showCreateLink"
+ >
+ <a
+ (click)="navigate(statusBox.createLink)"
+ fxLayoutAlign="start center"
+ class="status-container-create-link"
+ >
+ <i class="material-icons">add_circle</i>
+ <span> {{ statusBox.createTitle }}</span>
+ </a>
+ </div>
</div>
- <div class="status-container-text">pipelines running</div>
</div>
</div>
- <div
- fxFlex="25"
- class="status-container notifications mr-20"
- (click)="navigate('notifications')"
- >
- <div fxFill="100" fxLayout="column" fxLayoutAlign="center center">
- <div class="status-container-number" fxLayoutAlign="start center">
- {{ unreadNotificationCount }}
- </div>
- <div class="status-container-text">unread notifications</div>
- </div>
- </div>
- <div
- fxFlex="25"
- class="status-container pipeline-elements-installed"
- (click)="navigate('add')"
- >
- <div fxFill="100" fxLayout="column" fxLayoutAlign="center center">
- <div class="status-container-number" fxLayoutAlign="start center">
- {{ availablePipelineElements }}
- </div>
- <div class="status-container-text">installed pipeline
elements</div>
- </div>
+ <div fxLayoutAlign="start start">
+ <i class="material-icons status-container-icon">{{ statusBox.icon
}}</i>
</div>
</div>
diff --git a/ui/src/app/home/components/status.component.scss
b/ui/src/app/home/components/status.component.scss
index 500aeec2d0..d37adca327 100644
--- a/ui/src/app/home/components/status.component.scss
+++ b/ui/src/app/home/components/status.component.scss
@@ -18,30 +18,18 @@
.status-container {
height: 150px;
- width: 80%;
- color: white;
+ width: 100%;
+ color: var(--color-primary);
border-radius: 5px;
margin-bottom: 20px;
-}
-
-.status-container.pipelines {
- background: var(--color-accent);
-}
-
-.status-container.pipelines-running {
- background: rgb(59, 92, 149);
-}
-
-.status-container.notifications {
- background: rgb(88, 114, 146);
-}
-
-.status-container.pipeline-elements-installed {
- background: rgb(156, 156, 156);
+ border: 2px solid var(--color-bg-2);
+ background: var(--color-bg-2);
+ border-bottom: 5px solid var(--color-accent);
}
.status-container-number {
- font-size: 46pt;
+ font-size: 36pt;
+ font-weight: bold;
}
.status-container:hover {
@@ -50,9 +38,19 @@
}
.status-container-text {
- font-size: 16pt;
+ font-size: 15pt;
+}
+
+.status-container-create-link {
+ font-size: 12pt;
+ color: var(--color-accent);
+}
+
+.status-container-create-link:hover {
+ font-weight: bold;
}
-.mr-20 {
- margin-right: 20px;
+.status-container-icon {
+ font-size: 50pt;
+ color: var(--color-bg-3);
}
diff --git a/ui/src/app/home/components/status.component.ts
b/ui/src/app/home/components/status.component.ts
index 6a22d8c2a4..08ba999a59 100644
--- a/ui/src/app/home/components/status.component.ts
+++ b/ui/src/app/home/components/status.component.ts
@@ -18,11 +18,10 @@
import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';
-import { NotificationCountService } from
'../../services/notification-count-service';
-import {
- PipelineElementService,
- PipelineService,
-} from '@streampipes/platform-services';
+import { UserInfo } from '@streampipes/platform-services';
+import { StatusBox } from '../models/home.model';
+import { UserRole } from '../../_enums/user-role.enum';
+import { zip } from 'rxjs';
@Component({
selector: 'sp-status',
@@ -30,31 +29,49 @@ import {
styleUrls: ['./status.component.scss'],
})
export class StatusComponent implements OnInit {
- unreadNotificationCount = 0;
-
@Input()
- availablePipelines = 0;
+ statusBox: StatusBox;
@Input()
- availablePipelineElements = 0;
+ resourceCount: number = 0;
@Input()
- runningPipelines = 0;
+ currentUser: UserInfo;
+
+ showCreateLink = true;
- constructor(
- private pipelineElementService: PipelineElementService,
- private router: Router,
- public notificationCountService: NotificationCountService,
- private pipelineService: PipelineService,
- ) {}
+ constructor(private router: Router) {}
ngOnInit() {
- this.notificationCountService.unreadNotificationCount$.subscribe(
- count => (this.unreadNotificationCount = count),
- );
+ zip(this.statusBox.dataFns).subscribe(res => {
+ let totalLength = 0;
+ res.forEach(response => {
+ totalLength += response.length;
+ });
+
+ this.resourceCount = totalLength;
+ });
+ this.showCreateLink = this.shouldShowCreateLink();
+ }
+
+ shouldShowCreateLink(): boolean {
+ if (this.statusBox.createRoles.length === 0) {
+ return false;
+ } else if (this.hasRole(UserRole.ROLE_ADMIN)) {
+ return true;
+ } else {
+ const userRoles = this.currentUser.roles;
+ return userRoles.some(role =>
+ this.statusBox.createRoles.includes(role as UserRole),
+ );
+ }
+ }
+
+ hasRole(role: UserRole): boolean {
+ return this.currentUser.roles.indexOf(role) > -1;
}
- navigate(url: string) {
- this.router.navigate([url]);
+ navigate(command: string[]) {
+ this.router.navigate(command);
}
}
diff --git a/ui/src/app/home/home.component.html
b/ui/src/app/home/home.component.html
index 7bb10fca25..9912bca530 100644
--- a/ui/src/app/home/home.component.html
+++ b/ui/src/app/home/home.component.html
@@ -24,25 +24,25 @@
<div class="welcome-text">Welcome!</div>
</div>
<div fxLayout="column" fxFlex="100" class="home-margin">
- <div fxFlex="100" fxLayoutAlign="start center">
+ <div
+ fxFlex="100"
+ fxLayout="row"
+ fxLayoutAlign="start center"
+ fxLayoutGap="10px"
+ *ngIf="showStatus"
+ >
<sp-status
- fxFlex="100"
- [availablePipelineElements]="
- availablePipelineElements.length
- "
- [availablePipelines]="availablePipelines.length"
- [runningPipelines]="runningPipelines.length"
- *ngIf="showStatus"
+ [fxFlex]="100 / statusBoxes.length"
+ [statusBox]="box"
+ [currentUser]="currentUser"
+ *ngFor="let box of statusBoxes"
></sp-status>
</div>
<div fxFlex="100">
- <div
- class="assemblyOptions sp-blue-bg mt-0
round-border"
- style="padding: 5px"
+ <sp-basic-inner-panel
+ innerPadding="0"
+ panelTitle="{{ appConstants.APP_NAME }} Modules"
>
- <h4>{{ appConstants.APP_NAME }} Modules</h4>
- </div>
- <div class="sp-blue-border pt-0" fxLayout="column">
<div fxFlex="100" fxLayout="column">
<mat-list class="modules-list">
<mat-list-item
@@ -75,7 +75,7 @@
</mat-list-item>
</mat-list>
</div>
- </div>
+ </sp-basic-inner-panel>
</div>
</div>
</div>
diff --git a/ui/src/app/home/home.component.ts
b/ui/src/app/home/home.component.ts
index 0cb6585c43..e5e4e47c7a 100644
--- a/ui/src/app/home/home.component.ts
+++ b/ui/src/app/home/home.component.ts
@@ -40,6 +40,7 @@ import {
UserInfo,
} from '@streampipes/platform-services';
import { zip } from 'rxjs';
+import { StatusBox } from './models/home.model';
@Component({
templateUrl: './home.component.html',
@@ -54,6 +55,8 @@ export class HomeComponent implements OnInit {
availablePipelines: Pipeline[] = [];
runningPipelines: Pipeline[] = [];
+ statusBoxes: StatusBox[] = [];
+
requiredAdapterForTutorialAppId: any =
'org.apache.streampipes.connect.iiot.adapters.simulator.machine';
requiredProcessorForTutorialAppId: any =
@@ -78,12 +81,16 @@ export class HomeComponent implements OnInit {
private adapterService: AdapterService,
) {
this.serviceLinks = this.homeService.getFilteredServiceLinks();
+ this.statusBoxes = this.homeService
+ .getFilteredServiceLinks()
+ .filter(s => s.showStatusBox)
+ .map(s => s.statusBox);
}
ngOnInit() {
this.currentUser = this.currentUserService.getCurrentUser();
const isAdmin = this.hasRole(UserRole.ROLE_ADMIN);
- this.showStatus = isAdmin ||
this.hasRole(UserRole.ROLE_PIPELINE_ADMIN);
+ this.showStatus = true;
if (isAdmin) {
this.loadResources();
}
@@ -214,7 +221,6 @@ export class HomeComponent implements OnInit {
.concat(...res[2])
.concat(...res[3])
.concat(...res[4]);
-
this.checkForTutorial();
});
}
diff --git a/ui/src/app/home/home.module.ts b/ui/src/app/home/home.module.ts
index 469762ddc3..7693633a09 100644
--- a/ui/src/app/home/home.module.ts
+++ b/ui/src/app/home/home.module.ts
@@ -29,6 +29,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatListModule } from '@angular/material/list';
import { PlatformServicesModule } from '@streampipes/platform-services';
import { WelcomeTourComponent } from
'./dialog/welcome-tour/welcome-tour.component';
+import { SharedUiModule } from '@streampipes/shared-ui';
@NgModule({
imports: [
@@ -40,6 +41,7 @@ import { WelcomeTourComponent } from
'./dialog/welcome-tour/welcome-tour.compone
MatDividerModule,
MatListModule,
PlatformServicesModule,
+ SharedUiModule,
],
declarations: [HomeComponent, StatusComponent, WelcomeTourComponent],
providers: [HomeService],
diff --git a/ui/src/app/home/components/status.component.scss
b/ui/src/app/home/models/home.model.ts
similarity index 55%
copy from ui/src/app/home/components/status.component.scss
copy to ui/src/app/home/models/home.model.ts
index 500aeec2d0..d27ae16a27 100644
--- a/ui/src/app/home/components/status.component.scss
+++ b/ui/src/app/home/models/home.model.ts
@@ -16,43 +16,33 @@
*
*/
-.status-container {
- height: 150px;
- width: 80%;
- color: white;
- border-radius: 5px;
- margin-bottom: 20px;
-}
-
-.status-container.pipelines {
- background: var(--color-accent);
-}
-
-.status-container.pipelines-running {
- background: rgb(59, 92, 149);
-}
-
-.status-container.notifications {
- background: rgb(88, 114, 146);
-}
-
-.status-container.pipeline-elements-installed {
- background: rgb(156, 156, 156);
-}
-
-.status-container-number {
- font-size: 46pt;
-}
-
-.status-container:hover {
- cursor: pointer;
- opacity: 0.8;
-}
-
-.status-container-text {
- font-size: 16pt;
-}
-
-.mr-20 {
- margin-right: 20px;
+import { Observable } from 'rxjs';
+import { PageName } from '../../_enums/page-name.enum';
+import { UserRole } from '../../_enums/user-role.enum';
+
+export interface StatusBox {
+ link: string[];
+ createLink: string[];
+ title: string;
+ createTitle: string;
+ dataFns: Observable<any>[];
+ viewRoles: UserRole[];
+ createRoles: UserRole[];
+ icon: string;
+}
+
+export interface Link {
+ newWindow: boolean;
+ value: string;
+}
+
+export interface ServiceLink {
+ name: string;
+ description: string;
+ icon: string;
+ pageNames: PageName[];
+ link: Link;
+ showStatusBox: boolean;
+ statusBox?: StatusBox;
+ disableCreateLink?: boolean;
}