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>&nbsp;{{ 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;
 }

Reply via email to