diff options
Diffstat (limited to 'so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/home')
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]; +} |