aboutsummaryrefslogtreecommitdiffstats
path: root/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home
diff options
context:
space:
mode:
Diffstat (limited to 'so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home')
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.html205
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.scss130
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.spec.ts178
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.ts140
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.constant.ts41
5 files changed, 694 insertions, 0 deletions
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.html b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.html
new file mode 100644
index 0000000..4fd8cc4
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.html
@@ -0,0 +1,205 @@
+<!--
+============LICENSE_START=======================================================
+Copyright (C) 2018 Ericsson. All rights reserved.
+================================================================================
+Licensed 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.
+
+SPDX-License-Identifier: Apache-2.0
+============LICENSE_END=========================================================
+
+@authors: ronan.kenny@ericsson.com, waqas.ikram@ericsson.com, andrei.barcovschi@ericsson.com
+-->
+
+<base href="/">
+
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+<link rel="stylesheet" ng-href="./home.component.scss">
+<div class="completeForm">
+ <div class="searchArea">
+
+ <!-- Dropdown Filter and TextBox for Service Instance Id -->
+ <div class="container-home">
+ <mat-form-field class="selectFilter">
+ <mat-select class="formatBox" [(value)]="searchData.selectedValueSII" placeholder="Select Filter">
+ <mat-option *ngFor="let option of options" [value]="option.value">{{option.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field class="valueInput">
+ <input matInput #searchValueSII type="text" [(ngModel)]="searchData.serviceInstanceId" placeholder="Service Instance Id">
+ </mat-form-field>
+ </div>
+
+ <!-- Dropdown Filter and TextBox for Request Id -->
+ <div class="container-home">
+ <mat-form-field class="selectFilter">
+ <mat-select class="formatBox" [(value)]="searchData.selectedValueRI" placeholder="Select Filter">
+ <mat-option *ngFor="let option of options" [value]="option.value">{{option.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field class="valueInput">
+ <input matInput #searchValueRI type="text" [(ngModel)]="searchData.requestId" placeholder="Request Id">
+ </mat-form-field>
+
+ <!-- Angular Start Date Picker -->
+ <mat-form-field class="startDate">
+ <input matInput #startDate [matDatepicker]="picker" [(ngModel)]="searchData.startDate" placeholder="Choose a start date">
+ <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
+ <mat-datepicker #picker></mat-datepicker>
+ </mat-form-field>
+
+ <!-- Dropdown box for Start Hour selection -->
+ <mat-form-field class="selectHour">
+ <mat-select class="formatBox" [(value)]="searchData.selectedStartHour" placeholder="Select Hour">
+ <mat-option *ngFor="let option of hourOptions" [value]="option">{{option}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+
+ <!-- Dropdown box for Start Minute selection -->
+ <mat-form-field class="selectMinute">
+ <mat-select class="formatBox" [(value)]="searchData.selectedStartMinute" placeholder="Select Minute">
+ <mat-option *ngFor="let option of minuteOptions" [value]="option">{{option}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+
+ <!-- Dropdown Filter and TextBox for Service Name -->
+ <div class="container-home">
+ <mat-form-field class="selectFilter">
+ <mat-select class="formatBox" [(value)]="searchData.selectedValueSN" placeholder="Select Filter">
+ <mat-option *ngFor="let option of options" [value]="option.value">{{option.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field class="valueInput">
+ <input matInput #searchValueSN type="text" [(ngModel)]="searchData.serviceInstanceName" placeholder="Service Name">
+ </mat-form-field>
+
+ <!-- Angular End Date Picker -->
+ <mat-form-field class="endDate">
+ <input matInput #endDate [matDatepicker]="endpicker" [(ngModel)]="searchData.endDate" placeholder="Choose an end date">
+ <mat-datepicker-toggle matSuffix [for]="endpicker"></mat-datepicker-toggle>
+ <mat-datepicker #endpicker></mat-datepicker>
+ </mat-form-field>
+
+ <!-- Dropdown box for End Hour selection -->
+ <mat-form-field class="selectHour">
+ <mat-select class="formatBox" [(value)]="searchData.selectedEndHour" placeholder="Select Hour">
+ <mat-option *ngFor="let option of hourOptions" [value]="option">{{option}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+
+ <!-- Dropdown box for End Minute selection -->
+ <mat-form-field class="selectMinute">
+ <mat-select class="formatBox" [(value)]="searchData.selectedEndMinute" placeholder="Select Minute">
+ <mat-option *ngFor="let option of minuteOptions" [value]="option">{{option}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+
+ <!-- Dropdown Filter for Status -->
+ <div class="container-home">
+ <mat-form-field class="selectFilter">
+ <mat-select class="formatBox" [(value)]="searchData.selectedValueSTATUS" placeholder="Status">
+ <mat-option *ngFor="let statusOption of statusOptions" [value]="statusOption.value">{{ statusOption.name }}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+ <br />
+
+ <!-- Button to call makeCall() function to commence search based on parameters -->
+ <button (click)="makeCall()" class="fa fa-search"></button>
+ </div>
+
+ <br />
+
+ <!-- Table to display selected fields if data present -->
+ <div class="example-container mat-elevation-z8">
+ <mat-tab-group class="tab-group">
+ <mat-tab label="Service Instances">
+ <mat-table [dataSource]="processData" matSort>
+ <ng-container matColumnDef="requestId">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Request Id </mat-header-cell>
+ <mat-cell *matCellDef="let process"><a routerLink="" (click)="getProcessInstanceId(process.requestId)">{{ process.requestId }}</a></mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="serviceInstanceId">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Instance Id </mat-header-cell>
+ <mat-cell *matCellDef="let process"> {{ process.serviceInstanceId }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="serviceInstanceName">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Instance Name </mat-header-cell>
+ <mat-cell *matCellDef="let process"> {{ process.serviceInstanceName }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="networkId">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Network Id </mat-header-cell>
+ <mat-cell *matCellDef="let process"> {{ process.networkId }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="requestStatus">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Request Status </mat-header-cell>
+ <mat-cell *matCellDef="let process"> {{ process.requestStatus }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="serviceType">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Service Type </mat-header-cell>
+ <mat-cell *matCellDef="let process"> {{ process.serviceType }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="startTime">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Start Time </mat-header-cell>
+ <mat-cell *matCellDef="let process"> {{ (process.startTime | date:'yyyy-MM-dd HH:mm:sss Z') }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="endTime">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> End Time </mat-header-cell>
+ <mat-cell *matCellDef="let process"> {{ (process.endTime | date:'yyyy-MM-dd HH:mm:sss Z') }} </mat-cell>
+ </ng-container>
+ <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
+ </mat-table>
+ <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons>
+ </mat-paginator>
+ </mat-tab>
+
+ <mat-tab label="Service Statistics">
+ <div id="servStats">
+ <table class="statsTable">
+ <tbody>
+ <tr>
+ <td>Total: {{ totalVal }}</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Complete: {{ completeVal }}</td>
+ <td> {{ percentageComplete }}%</td>
+ </tr>
+ <tr>
+ <td>Failed: {{ failedVal }}</td>
+ <td> {{ percentageFailed }}%</td>
+ </tr>
+ <tr>
+ <td>In Progress: {{ inProgressVal }}</td>
+ <td> {{ percentageInProg }}%</td>
+ </tr>
+ <tr>
+ <td>Pending: {{ pendingVal }}</td>
+ <td> {{ percentagePending }}%</td>
+ </tr>
+ <tr>
+ <td>Unlocked: {{ unlockedVal }}</td>
+ <td> {{ percentageUnlocked }}%</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </mat-tab>
+ </mat-tab-group>
+ </div>
+</div>
+
+<ngx-spinner bdColor="rgba(51, 51, 51, 0.8)" size="large" color="#00285f" type="ball-spin-clockwise-fade-rotating"></ngx-spinner>
+<router-outlet></router-outlet>
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.scss b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.scss
new file mode 100644
index 0000000..9260e4c
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.scss
@@ -0,0 +1,130 @@
+/**
+============LICENSE_START=======================================================
+Copyright (C) 2018 Ericsson. All rights reserved.
+================================================================================
+Licensed 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.
+
+SPDX-License-Identifier: Apache-2.0
+============LICENSE_END=========================================================
+
+@authors: ronan.kenny@ericsson.com, waqas.ikram@ericsson.com
+*/
+@import "~@angular/material/prebuilt-themes/indigo-pink.css";
+
+.searchArea {
+ background-color: white;
+ padding: 10px;
+ height: 345px;
+ box-shadow: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);
+}
+
+.mat-form-field-appearance-legacy .mat-form-field-wrapper {
+ padding-bottom: 1.25em;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.selectFilter {
+ width: 120px;
+}
+
+.valueInput {
+ width: 400px;
+ margin-left: 30px;
+}
+
+.selectFilter.mat-select.ng-tns-c5-1.ng-star-inserted {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+}
+
+.mat-form-field-flex .valueInput {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+}
+
+.mat-primary .mat-option.mat-selected:not(.mat-option-disabled) {
+ color: #00285F;
+}
+
+.mat-option {
+ font-size: 17px;
+ line-height: 3em;
+ height: 3em;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.mat-select-arrow {
+ color: #00285F;
+}
+
+.mat-form-field.mat-focused.mat-primary .mat-select-arrow {
+ color: #00285F;
+}
+
+.mat-form-field-appearance-legacy .mat-form-field-underline {
+ color: #00285F;
+}
+
+.fa {
+ float: left;
+ width: 120px;
+ padding: 10px;
+ background: #2196F3;
+ color: white;
+ height: 40px;
+ font-size: 17px;
+ border: 1px solid grey;
+ border-left: none;
+ cursor: pointer;
+}
+
+form.example button:hover {
+ background: #0b7dda;
+}
+
+form.example::after {
+ content: "";
+ clear: both;
+ display: table;
+}
+
+.formFields {
+ display: inline-flex;
+}
+
+.endDate,
+.startDate {
+ margin-left: 90px;
+ width: 140px;
+}
+
+.selectHour,
+.selectMinute {
+ margin-left: 30px;
+ width: 100px;
+}
+
+#servStats {
+ background-color: white;
+ padding: 10px;
+ font-size: 17px;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.statsTable {
+ td {
+ padding: 12px 80px 12px 12px;
+ text-align: left;
+ border-bottom: 1px solid #ccc;
+ }
+}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.spec.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.spec.ts
new file mode 100644
index 0000000..0da24cc
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.spec.ts
@@ -0,0 +1,178 @@
+/**
+============LICENSE_START=======================================================
+ Copyright (C) 2018 Ericsson. All rights reserved.
+================================================================================
+Licensed 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.
+
+SPDX-License-Identifier: Apache-2.0
+============LICENSE_END=========================================================
+
+@authors: ronan.kenny@ericsson.com, waqas.ikram@ericsson.com, andrei.barcovschi@ericsson.com
+*/
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HomeComponent } from './home.component';
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { MatTableModule, MatNativeDateModule, MatTableDataSource, MatPaginatorModule } from '@angular/material';
+import { FormsModule } from '@angular/forms';
+import { MatDatepickerModule } from '@angular/material/datepicker';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { HttpClientModule } from '@angular/common/http';
+import { HttpClient } from '@angular/common/http';
+import { inject } from '@angular/core/testing';
+import { RouterModule } from '@angular/router';
+import { APP_BASE_HREF } from '@angular/common';
+import { ToastrNotificationService } from '../toastr-notification-service.service';
+import { environment } from '../../environments/environment.prod';
+import { Observable, of, throwError } from 'rxjs';
+import { SearchRequest } from '../model/SearchRequest.model';
+import { DataService } from '../data.service'; // may be able to remove
+import { BpmnInfraRequest } from '../model/bpmnInfraRequest.model';
+import { By } from '@angular/platform-browser';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { ProcessInstanceId } from '../model/processInstanceId.model';
+import { HttpResponse } from '@angular/common/http';
+import { Router } from '@angular/router';
+import { Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+import { DetailsComponent } from '../details/details.component';
+
+// Generate stub for toastr popup notifications
+class StubbedToastrNotificationService extends ToastrNotificationService {
+ toastrSettings() {}
+ info() {}
+ error() {}
+}
+
+const routes: Routes = [ { path: 'details/114e9ae4-4a32-11e9-8646-d663bd873d93' , component: DetailsComponent} ]
+
+describe('HomeComponent', () => {
+ let spyDataService: jasmine.SpyObj<DataService>;
+ let router: Router;
+ let component: HomeComponent;
+ let fixture: ComponentFixture<HomeComponent>;
+
+ beforeEach(() => {
+ spyDataService = jasmine.createSpyObj('DataService', ['getBpmnInfraRequest', 'getProcessInstanceId']);
+
+ TestBed.configureTestingModule({
+ providers: [
+ { provide: DataService, useValue: spyDataService },
+ { provide: APP_BASE_HREF, useValue: '/' },
+ { provide: ToastrNotificationService, useClass: StubbedToastrNotificationService }],
+ imports: [MatPaginatorModule, BrowserAnimationsModule, MatTableModule, FormsModule, MatDatepickerModule, MatNativeDateModule, HttpClientModule, RouterTestingModule.withRoutes(routes)],
+ declarations: [HomeComponent, DetailsComponent],
+ schemas: [
+ CUSTOM_ELEMENTS_SCHEMA
+ ]
+ });
+
+ fixture = TestBed.createComponent(HomeComponent);
+ router = TestBed.get(Router);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ // Ensure creation of HomeComponent component
+ it('component should be created', () => {
+ expect(component).toBeTruthy();
+ });
+
+ // Ensure all statistic variables are initialised to zero
+ it('should ensure statistic variables are defaulted at zero', () => {
+ expect(component.totalVal === 0 && component.completeVal === 0 &&
+ component.inProgressVal === 0 && component.failedVal === 0 &&
+ component.pendingVal === 0 && component.unlockedVal === 0 &&
+ component.percentageComplete === 0 && component.percentageFailed === 0 &&
+ component.percentageInProg === 0 && component.percentagePending === 0 &&
+ component.percentageUnlocked === 0).toBeTruthy();
+ });
+
+ it('should should navigate to a process if response status is OK', async(() => {
+ spyDataService.getProcessInstanceId.and.returnValue(of(<HttpResponse<ProcessInstanceId>>{body: {processInstanceId: '114e9ae4-4a32-11e9-8646-d663bd873d93'}, status: 200}));
+ spyOn(router, 'navigate');
+ component.getProcessInstanceId('e8a75940-4a32-11e9-8646-d663bd873d93');
+
+ fixture.whenStable().then(() => {
+ expect(router.navigate).toHaveBeenCalledWith(['/details/114e9ae4-4a32-11e9-8646-d663bd873d93']);
+ });
+ }));
+
+ it('should handle error if no process instance id found', () => {
+ spyDataService.getProcessInstanceId.and.returnValue(of(<HttpResponse<ProcessInstanceId>>{body: {processInstanceId: 'getProcessInstanceId error not found'}, status: 404}));
+ component.getProcessInstanceId('e8a75940-4a32-11e9-8646-d663bd873d93');
+ });
+
+ it('should handle error when searchData.getSearchRequest returns an error', () => {
+ spyOn(component.searchData, 'getSearchRequest').and.callFake(() => {
+ return throwError(new Error('getSearchRequest error'));
+ });
+ component.makeCall();
+ });
+
+ it('should handle error when dataService.getBpmnInfraRequest returns an error', () => {
+ spyOn(component.searchData, 'getSearchRequest').and.returnValue(of(getSearchRequest("965d3c92-44e0-11e9-b210-d663bd873d93", "85a7c354-44e0-11e9-b210-d663bd873d93", undefined, undefined, undefined, undefined, undefined, undefined, "ALL")));
+ spyDataService.getBpmnInfraRequest.and.callFake(() => {
+ return throwError(new Error('getBpmnInfraRequest error'));
+ });
+ component.makeCall();
+ });
+
+ it('should calculate statistics correctly', async(() => {
+ let requestStatusTypes: string[] = ["COMPLETE", "IN_PROGRESS", "FAILED", "PENDING", "UNLOCKED"];
+ let processArr: BpmnInfraRequest[] = [];
+
+ // create 5 processes, one of each requestStatusType, with default time.
+ requestStatusTypes.forEach((status) => {
+ let serviceName = "service-" + status;
+ var process = getProcess("85a7c354-44e0-11e9-b210-d663bd873d93", "965d3c92-44e0-11e9-b210-d663bd873d93", serviceName, "048a6212-44e1-11e9-b210-d663bd873d93", status, "TestType", undefined, undefined);
+ processArr.push(process);
+ })
+
+ // search request has default filter.
+ spyOn(component.searchData, 'getSearchRequest').and.returnValue(of(getSearchRequest(undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, "ALL")));
+ spyDataService.getBpmnInfraRequest.and.returnValue(of(processArr));
+ component.makeCall();
+
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+
+ expect(
+ component.totalVal === 5 && component.completeVal === 1 &&
+ component.inProgressVal === 1 && component.failedVal === 1 &&
+ component.pendingVal === 1 && component.unlockedVal === 1 &&
+ component.percentageComplete === 20 &&
+ component.percentageFailed === 20 &&
+ component.percentageInProg === 20 &&
+ component.percentagePending === 20 &&
+ component.percentageUnlocked === 20)
+ .toBeTruthy();
+ });
+ }));
+
+ function getSearchRequest(selectedValueSII = "EQ", serviceInstanceIdVal: string, selectedValueRI = "EQ", requestIdVal: string, selectedValueSN = "EQ", serviceInstanceNameVal: string, startTimeInMilliseconds = 0, endTimeInMilliseconds = 4, selectedValueSTATUS?: string): SearchRequest {
+ if (startTimeInMilliseconds > endTimeInMilliseconds) {
+ console.error("End time cannot be greater than start time.");
+ return undefined;
+ }
+ if (typeof selectedValueSTATUS === "string")
+ return new SearchRequest({ serviceInstanceId: [selectedValueSII, serviceInstanceIdVal], requestId: [selectedValueRI, requestIdVal], serviceInstanceName: [selectedValueSN, serviceInstanceNameVal], requestStatus: ["EQ", selectedValueSTATUS] }, startTimeInMilliseconds, endTimeInMilliseconds);
+ else
+ return new SearchRequest({ serviceInstanceId: [selectedValueSII, serviceInstanceIdVal], requestId: [selectedValueRI, requestIdVal], serviceInstanceName: [selectedValueSN, serviceInstanceNameVal] }, startTimeInMilliseconds, endTimeInMilliseconds);
+ }
+
+ function getProcess(requestIdVal: string, serviceInstanceIdVal: string, serviceInstanceNameVal: string, networkIdVal: string, requestStatusVal: string, serviceTypeVal: string, startTimeVal = "1", endTimeVal = "2"): BpmnInfraRequest {
+ return <BpmnInfraRequest>{ requestId: requestIdVal, serviceInstanceId: serviceInstanceIdVal, serviceInstanceName: serviceInstanceNameVal, networkId: networkIdVal, requestStatus: requestStatusVal, serviceType: serviceTypeVal, startTime: startTimeVal, endTime: endTimeVal };
+ }
+});
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.ts
new file mode 100644
index 0000000..01e6899
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.component.ts
@@ -0,0 +1,140 @@
+/**
+============LICENSE_START=======================================================
+ Copyright (C) 2018 Ericsson. All rights reserved.
+================================================================================
+Licensed 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.
+
+SPDX-License-Identifier: Apache-2.0
+============LICENSE_END=========================================================
+
+@authors: ronan.kenny@ericsson.com, waqas.ikram@ericsson.com, andrei.barcovschi@ericsson.com
+*/
+
+import { Component, OnInit, ViewChild, ElementRef, Input, ViewEncapsulation } from '@angular/core';
+import { DataService } from '../data.service';
+import { ActivatedRoute, Router } from "@angular/router";
+import { BpmnInfraRequest } from '../model/bpmnInfraRequest.model';
+import { ProcessInstanceId } from '../model/processInstanceId.model';
+import { ToastrNotificationService } from '../toastr-notification-service.service';
+import { MatSelectModule } from '@angular/material/select';
+import { FormsModule, FormControl } from '@angular/forms';
+import { SearchData } from '../model/searchData.model';
+import { MatDatepickerModule } from '@angular/material/datepicker';
+import { SearchRequest } from '../model/SearchRequest.model';
+import { NgxSpinnerService } from 'ngx-spinner';
+import { MatFormFieldModule, MatInputModule, MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
+import { Constants } from './home.constant';
+
+@Component({
+ selector: 'app-home',
+ templateUrl: './home.component.html',
+ styleUrls: ['./home.component.scss'],
+ encapsulation: ViewEncapsulation.None
+})
+
+export class HomeComponent {
+
+ totalVal = 0;
+ completeVal = 0;
+ inProgressVal = 0;
+ failedVal = 0;
+ pendingVal = 0;
+ unlockedVal = 0;
+ percentageComplete = 0;
+ percentageFailed = 0;
+ percentageInProg = 0;
+ percentagePending = 0;
+ percentageUnlocked = 0;
+
+ options = Constants.OPTIONS;
+ statusOptions = Constants.STATUS_OPTIONS;
+ hourOptions = Constants.HOUR_OPTIONS;
+ minuteOptions = Constants.MINUTE_OPTIONS;
+ displayedColumns = Constants.DISPLAYED_COLUMNS;
+ pageSizeOptions = Constants.DEFAULT_PAGE_SIZE_OPTIONS;
+
+ searchData: SearchData;
+ startingDate: Date;
+ processData: MatTableDataSource<BpmnInfraRequest>;
+
+ @ViewChild(MatPaginator) paginator: MatPaginator;
+ @ViewChild(MatSort) sort: MatSort;
+
+ constructor(private route: ActivatedRoute, private data: DataService,
+ private router: Router, private popup: ToastrNotificationService,
+ private spinner: NgxSpinnerService) {
+ this.searchData = new SearchData();
+ }
+
+ makeCall() {
+ this.spinner.show();
+
+ var search = this.searchData.getSearchRequest().subscribe((result: SearchRequest) => {
+
+ this.data.getBpmnInfraRequest(result.getFilters(), result.getStartTimeInMilliseconds(), result.getEndTimeInMilliseconds())
+ .subscribe((data: BpmnInfraRequest[]) => {
+ this.spinner.hide();
+ var processData: BpmnInfraRequest[] = data;
+ this.processData = new MatTableDataSource<BpmnInfraRequest>(processData);
+ this.processData.sort = this.sort;
+ this.processData.paginator = this.paginator;
+ this.processData.paginator.firstPage();
+
+ this.popup.info("Number of records found: " + data.length)
+
+ // Calculate Statistics for Service Statistics tab
+ this.completeVal = processData.filter(i => i.requestStatus === "COMPLETE").length;
+ this.inProgressVal = processData.filter(i => i.requestStatus === "IN_PROGRESS").length;
+ this.failedVal = processData.filter(i => i.requestStatus === "FAILED").length;
+ this.pendingVal = processData.filter(i => i.requestStatus === "PENDING").length;
+ this.unlockedVal = processData.filter(i => i.requestStatus === "UNLOCKED").length;
+ this.totalVal = processData.length;
+
+ // Calculate percentages to 2 decimal places and compare to 0 to avoid NaN error
+ if (this.totalVal != 0) {
+ this.percentageComplete = Math.round(((this.completeVal / this.totalVal) * 100) * 100) / 100;
+ this.percentageFailed = Math.round(((this.failedVal / this.totalVal) * 100) * 100) / 100;
+ this.percentageInProg = Math.round(((this.inProgressVal / this.totalVal) * 100) * 100) / 100;
+ this.percentagePending = Math.round(((this.pendingVal / this.totalVal) * 100) * 100) / 100;
+ this.percentageUnlocked = Math.round(((this.unlockedVal / this.totalVal) * 100) * 100) / 100;
+ }
+ console.log("COMPLETE: " + this.completeVal);
+ console.log("FAILED: " + this.failedVal);
+ }, error => {
+ console.log(error);
+ this.popup.error("Unable to perform search Error code:" + error.status);
+ this.spinner.hide();
+ });
+ }, error => {
+ console.log("Data validation error " + error);
+ this.popup.error(error);
+ this.spinner.hide();
+ });
+ }
+
+ getProcessInstanceId(requestId: string) {
+ this.spinner.show();
+
+ var response = this.data.getProcessInstanceId(requestId).subscribe((data) => {
+ if (data.status == 200) {
+ this.spinner.hide();
+ var processInstanceId = (data.body as ProcessInstanceId).processInstanceId;
+ this.router.navigate(['/details/' + processInstanceId]);
+ } else {
+ this.popup.error('No process instance id found: ' + requestId);
+ this.spinner.hide();
+ console.log('No process instance id found: ' + requestId);
+ }
+ });
+ }
+}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.constant.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.constant.ts
new file mode 100644
index 0000000..72c98af
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home/home.constant.ts
@@ -0,0 +1,41 @@
+
+/**
+============LICENSE_START=======================================================
+ Copyright (C) 2019 Ericsson. All rights reserved.
+================================================================================
+Licensed 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.
+
+SPDX-License-Identifier: Apache-2.0
+============LICENSE_END=========================================================
+
+@authors: andrei.barcovschi@ericsson.com, waqas.ikram@ericsson.com
+*/
+
+export class Constants {
+ public static OPTIONS = [{ name: "EQUAL", value: "EQ" }, { name: "NOT EQUAL", value: "NEQ" }, { name: "LIKE", value: "LIKE" }];
+
+ public static STATUS_OPTIONS = [{ name: "ALL", value: "ALL" }, { name: "COMPLETE", value: "COMPLETE" }, { name: "IN_PROGRESS", value: "IN_PROGRESS" },
+ { name: "FAILED", value: "FAILED" }, { name: "PENDING", value: "PENDING" }, { name: "UNLOCKED", value: "UNLOCKED" }];
+
+ public static HOUR_OPTIONS = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11",
+ "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"];
+
+ public static MINUTE_OPTIONS = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15",
+ "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35",
+ "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55",
+ "56", "57", "58", "59"];
+
+ public static DISPLAYED_COLUMNS = ['requestId', 'serviceInstanceId', 'serviceInstanceName', 'networkId', 'requestStatus', 'serviceType', 'startTime', 'endTime'];
+
+ public static DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
+}