From: Barath Kumar R Date: Mon, 1 Mar 2021 07:22:33 +0000 (+0530) Subject: Feature-9904: Enhancing NG-UI to enable Juju operational view dashboard X-Git-Tag: release-v10.0-start^0 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=f2ae5462f9c1d6b7a649eb389c5a4c990501b5c4;p=osm%2FNG-UI.git Feature-9904: Enhancing NG-UI to enable Juju operational view dashboard * NG-UI able to show the Juju Operational view dashboard of launched NS. Change-Id: I9c7feadce8dbfca00e4e9321dffed3818a2e4510 Signed-off-by: Barath Kumar R --- diff --git a/src/app/instances/InstancesModule.ts b/src/app/instances/InstancesModule.ts index 7e47d32..18c733c 100644 --- a/src/app/instances/InstancesModule.ts +++ b/src/app/instances/InstancesModule.ts @@ -39,6 +39,10 @@ import { Ng2SmartTableModule } from 'ng2-smart-table'; import { NSInstancesComponent } from 'NSInstancesComponent'; import { NSPrimitiveComponent } from 'NSPrimitiveComponent'; import { NSTopologyComponent } from 'NSTopologyComponent'; +import { OperationalViewAppActionsComponent } from 'OperationalAppActionsComponent'; +import { OperationalViewAppConfigsComponent } from 'OperationalAppConfigsComponent'; +import { OperationalViewAppExecutedActionsComponent } from 'OperationalAppExecutedActionsComponent'; +import { OperationalViewComponent } from 'OperationalViewComponent'; import { PagePerRowModule } from 'PagePerRowModule'; import { PageReloadModule } from 'PageReloadModule'; import { PDUInstancesComponent } from 'PDUInstancesComponent'; @@ -100,6 +104,23 @@ const routes: Routes = [ projectInfo, { title: 'NSINSTANCES', url: '/instances/ns' }, { title: '{id}', url: null }] }, component: NSTopologyComponent + }, + { + path: 'operational-view', + data: { + breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' }, + projectInfo, { title: 'PAGE.OPERATIONALDASHBOARD.TITLE', url: null }] + }, + component: OperationalViewComponent + }, + { + path: 'operational-view/:id', + data: { + breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' }, + projectInfo, { title: 'PAGE.OPERATIONALDASHBOARD.TITLE', url: '/instances/operational-view' }, + { title: '{id}', url: null }] + }, + component: OperationalViewComponent } ] } @@ -114,10 +135,17 @@ const routes: Routes = [ CodemirrorModule, CommonModule, Ng2SmartTableModule, FlexLayoutModule, RouterModule.forChild(routes), NgbModule, NgSelectModule, PagePerRowModule, LoaderModule, SidebarModule.forRoot(), PageReloadModule], declarations: [InstancesComponent, NSInstancesComponent, VNFInstancesComponent, PDUInstancesComponent, AddPDUInstancesComponent, - NetsliceInstancesComponent, HistoryOperationsComponent, NSTopologyComponent, NSPrimitiveComponent], + NetsliceInstancesComponent, HistoryOperationsComponent, NSTopologyComponent, NSPrimitiveComponent, OperationalViewComponent, + OperationalViewAppConfigsComponent, OperationalViewAppActionsComponent, OperationalViewAppExecutedActionsComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA], providers: [DataService], - entryComponents: [NSPrimitiveComponent, AddPDUInstancesComponent] + entryComponents: [ + NSPrimitiveComponent, + AddPDUInstancesComponent, + OperationalViewAppConfigsComponent, + OperationalViewAppActionsComponent, + OperationalViewAppExecutedActionsComponent + ] }) /** Exporting a class @exports InstancesModule */ export class InstancesModule { diff --git a/src/app/instances/ns-instances/NSInstancesComponent.ts b/src/app/instances/ns-instances/NSInstancesComponent.ts index 3f20710..7b81d91 100644 --- a/src/app/instances/ns-instances/NSInstancesComponent.ts +++ b/src/app/instances/ns-instances/NSInstancesComponent.ts @@ -242,7 +242,8 @@ export class NSInstancesComponent implements OnInit { adminDetails: nsdInstanceData._admin, vnfID: nsdInstanceData['vnfd-id'], nsd: nsdInstanceData.nsd, - 'nsd-id': nsdInstanceData['nsd-id'] + 'nsd-id': nsdInstanceData['nsd-id'], + vcaStatus: nsdInstanceData.vcaStatus }; this.nsInstanceData.push(nsDataObj); }); diff --git a/src/app/operational-view/OperationalViewComponent.html b/src/app/operational-view/OperationalViewComponent.html new file mode 100644 index 0000000..e23f6a4 --- /dev/null +++ b/src/app/operational-view/OperationalViewComponent.html @@ -0,0 +1,276 @@ + +
+
{{ 'PAGE.OPERATIONALDASHBOARD.TITLE' | translate }} + ({{ 'PAGE.OPERATIONALDASHBOARD.MODELSUMMARY' | translate }})
+ +
+
+ + + + +
+ {{vcaDetail.vca_name}} + {{vcaDetail.ns_id}} + +
+
+ +
+
+
+
+ + + + +
+ +
+
+
+
+
+ +
+ {{ 'PAGE.OPERATIONALDASHBOARD.MODEL' | translate }} {{i+1}} (Cloud/Region): + {{modelVCAStatus.model ? modelVCAStatus.model.cloud_tag : '-'}}/ + {{modelVCAStatus.model ? modelVCAStatus.model.region : '-' }} +
+
+
+
+
+ + + + + +
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'PAGE.OPERATIONALDASHBOARD.APPLICATION' | translate }} + {{ 'STATUS' | translate }}{{ 'SCALE' | translate }}{{ 'PAGE.OPERATIONALDASHBOARD.CHARM' | translate }}{{ 'PAGE.OPERATIONALDASHBOARD.STORE' | translate }}{{ 'ACTIONS' | translate }}
+ + + {{application.app_id ? application.app_id : '-' }} + {{application.status ? application.status : '-' }}{{application.scale ? application.scale : 0 }}{{application.charm ? application.charm : '-' }}{{application.store ? application.store : '-' }} +
+ + +
+
{{ 'PAGE.OPERATIONALDASHBOARD.NOAPPLICATION' | translate }} +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'PAGE.OPERATIONALDASHBOARD.UNITS' | translate }}{{ 'PAGE.OPERATIONALDASHBOARD.WORKLOAD' | translate }}{{ 'PAGE.OPERATIONALDASHBOARD.AGENT' | translate }}{{ 'PAGE.OPERATIONALDASHBOARD.MACHINE' | translate }} + {{ 'PUBLICADDRESS' | translate }} / + {{ 'PAGE.OPERATIONALDASHBOARD.ADDRESS' | translate }} + {{ 'PAGE.OPERATIONALDASHBOARD.MESSAGE' | translate }}
+ + + {{unit.unit_id ? unit.unit_id : '-'}} {{unit.leader !== null ? '(' + + ('PAGE.OPERATIONALDASHBOARD.LEADER' | translate) + ')' : '' }} + {{unit.workload_status ? unit.workload_status.status : '-'}}{{unit.agent_status ? unit.agent_status.status : '-'}}{{unit.machine ? unit.machine : '-'}} + {{unit.public_address ? unit.public_address : unit.address ? + unit.address : '-'}} + {{unit.workload_status ? unit.workload_status.info : '-'}}
{{ 'PAGE.OPERATIONALDASHBOARD.NOUNITS' | translate }}
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'PAGE.OPERATIONALDASHBOARD.MACHINE' | translate }}StateDNSInstance ID{{ 'PAGE.OPERATIONALDASHBOARD.SERIES' | translate }}{{ 'PAGE.OPERATIONALDASHBOARD.MESSAGE' | translate }}
{{machines.id_ ? machines.id_ : '-'}}{{machines.agent_status ? machines.agent_status.status : '-'}}{{machines.dns_name !== null ? machines.dns_name : '-'}}{{machines.instance_id ? machines.instance_id : '-'}}{{machines.series ? machines.series : '-'}}{{machines.instance_status ? machines.instance_status.info : '-'}}
+ {{ 'PAGE.OPERATIONALDASHBOARD.NOMACHINES' | translate }} +
+ + + + + + + + + + + + + + + + + + + + + +
+ {{ 'PAGE.OPERATIONALDASHBOARD.RELATIONPROVIDER' | translate }} + {{ 'PAGE.OPERATIONALDASHBOARD.REQUIRER' | translate }}{{ 'PAGE.OPERATIONALDASHBOARD.INTERFACE' | translate }}{{ 'TYPE' | translate }}
{{relation.key ? relation.key : '-'}}{{relation.key ? relation.key : '-'}}{{relation.interface ? relation.interface : '-'}}{{relation.endpoints[0].role ? relation.endpoints[0].role : '-'}}
{{ 'PAGE.OPERATIONALDASHBOARD.NORELATIONS' | translate }} +
+
+
+
+
+
+
+
+ +
{{ 'NODATA' | translate }}
+
+
+ \ No newline at end of file diff --git a/src/app/operational-view/OperationalViewComponent.ts b/src/app/operational-view/OperationalViewComponent.ts new file mode 100644 index 0000000..9d6c1fe --- /dev/null +++ b/src/app/operational-view/OperationalViewComponent.ts @@ -0,0 +1,396 @@ +/* + Copyright 2020 TATA ELXSI + + 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. + + Author: BARATH KUMAR R (barath.r@tataelxsi.co.in) +*/ + +/** + * @file Page for Operational View Component + */ +import { Component, Injector, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { CONSTANTNUMBER, ERRORDATA } from 'CommonModel'; +import { environment } from 'environment'; +import * as HttpStatus from 'http-status-codes'; +import { OperationalViewAppActionsComponent } from 'OperationalAppActionsComponent'; +import { OperationalViewAppConfigsComponent } from 'OperationalAppConfigsComponent'; +import { OperationalViewAppExecutedActionsComponent } from 'OperationalAppExecutedActionsComponent'; +import { EXECUTEDACTIONS, MACHINES, SET_TIMER, SETMODELS, SETTIMER, VCAAPPLICATIONS, VCADETAILS, VCASTATUS, VCAUNITS } from 'OperationalModel'; +import { RestService } from 'RestService'; +import { Observable } from 'rxjs'; +import { Subscription } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { SharedService } from 'SharedService'; +import { isNullOrUndefined } from 'util'; +/** + * Creating component + * @Component takes OperationalViewComponent.html as template url + */ +@Component({ + selector: 'app-operational-view', + templateUrl: './OperationalViewComponent.html' +}) +/** Exporting a class @exports OperationalViewComponent */ +export class OperationalViewComponent implements OnInit { + /** Invoke service injectors @public */ + public injector: Injector; + + /** Check the loading results @public */ + public isLoadingResults: boolean = false; + + /** Give the message for the loading @public */ + public message: string = 'PLEASEWAIT'; + + /** Formation of appropriate Data for vcaStatus Details @public */ + public vcaDetails: VCADETAILS[] = []; + + /** Contains all methods related to shared @public */ + public sharedService: SharedService; + + /** Utilizes rest service for any CRUD operations @public */ + public restService: RestService; + + /** variables contains activeID @public */ + public activeID: string = null; + + /** variables contains NS Instances ID @public */ + public instancesID: string = null; + + /** variables contains URL of operational Dashboard @public */ + public openURL: string = 'instances/operational-view/'; + + /** variables contains default seconds for the timeout @public */ + public timeOutDefaultSeconds: number = CONSTANTNUMBER.timeOutDefaultSeconds; + + /** variables contains minimum seconds for the timeout @public */ + public minSeconds: number = 5; + + /** variables contains maximum seconds for the timeout @public */ + public maxSeconds: number = 60; + + /** variables contains timer calculation value of milliseconds @public */ + public timeDefaultCal: number = 1000; + + /** variables contains timeout @public */ + public timeOut: number; + + /** Set the timer button @public */ + // tslint:disable-next-line: no-magic-numbers + public setSeconds: SETTIMER[] = SET_TIMER; + + /** Instance of subscriptions @private */ + private generateDataSub: Subscription; + + /** Contains tranlsate instance @private */ + private translateService: TranslateService; + + /** Holds teh instance of AuthService class of type AuthService @private */ + private activatedRoute: ActivatedRoute; + + /** Instance of the modal service @private */ + private modalService: NgbModal; + + /** creates Operational view component */ + constructor(injector: Injector) { + this.injector = injector; + this.restService = this.injector.get(RestService); + this.sharedService = this.injector.get(SharedService); + this.translateService = this.injector.get(TranslateService); + this.activatedRoute = this.injector.get(ActivatedRoute); + this.modalService = this.injector.get(NgbModal); + } + + /** + * Lifecyle Hooks the trigger before component is instantiate + */ + public ngOnInit(): void { + // tslint:disable-next-line:no-backbone-get-set-outside-model + this.instancesID = this.activatedRoute.snapshot.paramMap.get('id'); + this.generateData(); + this.generateDataSub = this.sharedService.dataEvent.subscribe((): void => { this.generateData(); }); + } + /** Fetching the juju vca_status data from API and Load it in the respective table @public */ + public generateData(): void { + this.clearTimeoutAndInterval(); + this.modalService.dismissAll(); + this.isLoadingResults = true; + this.vcaDetails = []; + let NSURL: string = environment.NSDINSTANCES_URL; + if (this.instancesID !== null) { + NSURL = NSURL + '/' + this.instancesID; + this.generateIndividualNSData(NSURL); + } else { + this.generateAllNSData(NSURL); + } + } + /** + * Show all NS Data that contains the juju vca_status from API and Load it in the table @public + * @param NSURL : osm/nslcm/v1/ns_instances + */ + public generateAllNSData(NSURL: string): void { + this.restService.getResource(NSURL).subscribe((operationalList: VCASTATUS[]): void => { + if (operationalList.length > 0) { + operationalList.forEach((list: VCASTATUS): void => { + if (!isNullOrUndefined(list.vcaStatus)) { + const getVCAStatusDetails: VCADETAILS = this.vcaDetailsData(list, false, this.timeOutDefaultSeconds); + this.vcaDetails.push(getVCAStatusDetails); + } + }); + if (this.activeID === null && this.vcaDetails.length > 0) { + this.activeID = this.vcaDetails[0].ns_id; + } + } + this.isLoadingResults = false; + }, (error: ERRORDATA): void => { + this.isLoadingResults = false; + this.restService.handleError(error, 'get'); + }); + } + /** + * Show the individual NS Data that contains the juju vca_status from generateNSData method and Load it in the table @public + * @param NSURL : osm/nslcm/v1/ns_instances/ + */ + public generateIndividualNSData(NSURL: string): void { + this.generateNSData(NSURL, false, this.timeOutDefaultSeconds).subscribe((getVCAStatusDetails: VCADETAILS): void => { + this.vcaDetails.push(getVCAStatusDetails); + if (this.activeID === null && this.vcaDetails.length > 0) { + this.activeID = this.instancesID; + } + this.isLoadingResults = false; + }, (error: ERRORDATA): void => { + this.isLoadingResults = false; + this.restService.handleError(error, 'get'); + }); + } + /** + * Fetching the Individual NS Data that contains the juju vca_status from API and return the VCADetails @public + * @param NSURL : osm/nslcm/v1/ns_instances/ + * @param liveData : Needs to repeat the httprequest + * @param timeOutSeconds : set the timeout seconds to trigger the httprequest + */ + public generateNSData(NSURL: string, liveData: boolean, timeOutSeconds: number): Observable { + if (liveData) { + NSURL = NSURL + '?vcaStatusRefresh=true'; + } + return this.restService.getResource(NSURL).pipe(map((operationalList: VCASTATUS): VCADETAILS => { + return this.vcaDetailsData(operationalList, liveData, timeOutSeconds); + })); + } + /** + * Form the VCA Details for each NS Instances + */ + public formVCADetails(getData: VCADETAILS): VCADETAILS { + return { + isLiveloading: getData.isLiveloading, + ns_id: getData.ns_id, + vcaStatusModels: getData.vcaStatusModels, + timeOutSeconds: getData.timeOutSeconds, + vca_id: getData.vca_id, + vca_name: getData.vca_name + }; + } + /** + * Assign the VCA Status of Multiple model in getModels array for each NS Instance + */ + public assignVCAStatusOfEachModel(getData: SETMODELS): SETMODELS { + return { + applications: getData.applications, + branches: getData.branches, + controller_timestamp: getData.controller_timestamp, + executedActions: getData.executedActions, + machines: getData.machines, + model: getData.model, + offers: getData.offers, + relations: getData.relations, + remote_applications: getData.remote_applications, + units: getData.units, + unknown_fields: getData.unknown_fields + }; + } + /** + * Use to fetch the vcaDetails from vca_status @public + */ + public vcaDetailsData(list: VCASTATUS, liveData: boolean, timeOutSeconds: number): VCADETAILS { + const assignVCADetails: VCADETAILS[] = []; + const setModels: SETMODELS[] = []; + const assignNSInstancesID: string = list.id; + Object.keys(list.vcaStatus).forEach((key: string): void => { + const vcaApplication: VCAAPPLICATIONS[] = this.appData(list.vcaStatus[key].applications); + const vcaUnits: VCAUNITS[] = this.unitsData(vcaApplication); + const vcaMachines: MACHINES[] = this.machinesData(list.vcaStatus[key].machines); + list.vcaStatus[key].units = vcaUnits; + list.vcaStatus[key].applications = vcaApplication; + list.vcaStatus[key].machines = vcaMachines; + list.vcaStatus[key].relations = list.vcaStatus[key].relations; + list.vcaStatus[key].model = list.vcaStatus[key].model; + const getEachModelData: SETMODELS = this.assignVCAStatusOfEachModel(list.vcaStatus[key]); + setModels.push(getEachModelData); + list.vcaStatus[assignNSInstancesID].vca_id = key; + list.vcaStatus[assignNSInstancesID].vca_name = list.name; + list.vcaStatus[assignNSInstancesID].ns_id = list.id; + list.vcaStatus[assignNSInstancesID].isLiveloading = liveData; + list.vcaStatus[assignNSInstancesID].timeOutSeconds = timeOutSeconds; + list.vcaStatus[assignNSInstancesID].vcaStatusModels = setModels; + const getAssignedData: VCADETAILS = this.formVCADetails(list.vcaStatus[assignNSInstancesID]); + assignVCADetails.push(getAssignedData); + }); + return assignVCADetails[0]; + } + /** + * Use to fetch the app data from vca_status @public + */ + public appData(applicationData: VCAAPPLICATIONS): VCAAPPLICATIONS[] { + const vcaApplication: VCAAPPLICATIONS[] = []; + Object.keys(applicationData).forEach((applicationKey: string): void => { + const charmSplitlist: string[] = applicationData[applicationKey].charm.split('/'); + const status: string = applicationData[applicationKey].status.status; + const charm: string = charmSplitlist[1].substr(0, charmSplitlist[1].lastIndexOf('-')); + const store: string = charmSplitlist[0].substr(0, charmSplitlist[0].lastIndexOf(':')); + applicationData[applicationKey].app_id = applicationKey; + applicationData[applicationKey].charm = charm; + applicationData[applicationKey].status = status; + applicationData[applicationKey].scale = Object.keys(applicationData[applicationKey].units).length; + applicationData[applicationKey].store = store; + applicationData[applicationKey].configs = !isNullOrUndefined(applicationData[applicationKey].configs) ? + applicationData[applicationKey].configs : null; + applicationData[applicationKey].actions = !isNullOrUndefined(applicationData[applicationKey].actions) ? + applicationData[applicationKey].actions : null; + vcaApplication.push(applicationData[applicationKey]); + }); + return vcaApplication; + } + /** + * Use to fetch the units data from vca_status @public + */ + public unitsData(applicationData: VCAAPPLICATIONS[]): VCAUNITS[] { + const vcaUnits: VCAUNITS[] = []; + applicationData.forEach((applicationList: VCAAPPLICATIONS): void => { + Object.keys(applicationList.units).forEach((unitsKey: string): void => { + applicationList.units[unitsKey].unit_id = unitsKey; + vcaUnits.push(applicationList.units[unitsKey]); + }); + }); + return vcaUnits; + } + /** + * Use to fetch the machines data from vca_status @public + */ + public machinesData(machinesData: MACHINES[]): MACHINES[] { + const vcaMachines: MACHINES[] = []; + Object.keys(machinesData).forEach((machineKey: string): void => { + vcaMachines.push(machinesData[machineKey]); + }); + return vcaMachines; + } + /** Show the Config list in modal using modalservice @public */ + public showExecutedActionsList(executeActionsList: EXECUTEDACTIONS[]): void { + this.modalService.open(OperationalViewAppExecutedActionsComponent, { size: 'xl', backdrop: 'static' }) + .componentInstance.params = { executedActions: executeActionsList }; + } + /** Show the Config list in modal using modalservice @public */ + public showConfigList(configList: object): void { + this.modalService.open(OperationalViewAppConfigsComponent, { size: 'xl', backdrop: 'static' }) + .componentInstance.params = { configs: configList }; + } + /** Show the Config list in modal using modalservice @public */ + public showActionsList(actionsList: object): void { + this.modalService.open(OperationalViewAppActionsComponent, { size: 'xl', backdrop: 'static' }) + .componentInstance.params = { actions: actionsList }; + } + /** Call the live data to fetch the latest results @public */ + public callLiveData(isChecked: boolean, getNSID: string, index: number): void { + this.vcaDetails[index].isLiveloading = isChecked; + if (isChecked) { + this.stopExistingModelLiveLoading(getNSID); + this.generateRefreshedData(getNSID, index, this.vcaDetails[index].timeOutSeconds); + } else { + this.clearTimeoutAndInterval(); + } + } + /** Fetching the juju vca_status data from API and Load it in the respective model @public */ + public generateRefreshedData(getNSID: string, index: number, secondsValue: number): void { + this.modalService.dismissAll(); + const liveDataURL: string = environment.NSDINSTANCES_URL + '/' + getNSID; + this.generateNSData(liveDataURL, true, secondsValue).subscribe((getVCAStatusDetails: VCADETAILS): void => { + this.vcaDetails[index] = getVCAStatusDetails; + this.callSetTimeOut(getNSID, index, secondsValue); + }, (error: ERRORDATA): void => { + this.restService.handleError(error, 'get'); + if (error.error.status === HttpStatus.NOT_FOUND) { + this.vcaDetails.splice(index, 1); + } + this.clearTimeoutAndInterval(); + }); + } + /** Call the setimeout to refresh the all models data in regular timeout @public */ + public callSetTimeOut(id: string, index: number, secondsValue: number): void { + this.clearTimeoutAndInterval(); + this.timeOut = window.setTimeout((): void => { + this.generateRefreshedData(id, index, secondsValue); + }, secondsValue * this.timeDefaultCal); + } + /** Stop existing model live reload @public */ + public stopExistingModelLiveLoading(getNSID: string): void { + this.clearTimeoutAndInterval(); + this.vcaDetails.forEach((vcaDetail: VCADETAILS, i: number): void => { + if (vcaDetail.ns_id !== getNSID) { + vcaDetail.isLiveloading = false; + } + }); + } + /** Method to show/hide the tables @public */ + public showHideTables(event: HTMLElement, getTableName: string, index: number): void { + let selectedClassName: string = getTableName + index; + if (selectedClassName === 'all' + index) { + selectedClassName = ''; + } + document.querySelectorAll('.filter' + index).forEach((button: HTMLElement): void => { + button.classList.remove('active'); + if (selectedClassName !== '') { + if (button.classList.contains(selectedClassName)) { + button.classList.add('active'); + } + } else if (button.classList.contains('all' + index)) { + button.classList.add('active'); + } + }); + document.querySelectorAll('.filterTable' + index).forEach((table: HTMLElement): void => { + table.classList.remove('hide'); + if (selectedClassName !== '') { + if (!table.classList.contains(selectedClassName)) { + table.classList.add('hide'); + } + } + }); + } + /** Get the timer selected @public */ + public onSetTimerSelector(getSeconds: number, nsID: string, index: number): void { + this.vcaDetails[index].timeOutSeconds = getSeconds; + this.callLiveData(true, nsID, index); + } + /** Clear settimeOut and setinterval @public */ + public clearTimeoutAndInterval(): void { + clearTimeout(this.timeOut); + } + /** + * Lifecyle hook which get trigger on component destruction + */ + public ngOnDestroy(): void { + this.clearTimeoutAndInterval(); + this.generateDataSub.unsubscribe(); + } +} diff --git a/src/app/operational-view/operational-view-app-actions/OperationalViewAppActionsComponent.html b/src/app/operational-view/operational-view-app-actions/OperationalViewAppActionsComponent.html new file mode 100644 index 0000000..08e6ec7 --- /dev/null +++ b/src/app/operational-view/operational-view-app-actions/OperationalViewAppActionsComponent.html @@ -0,0 +1,42 @@ + + + + \ No newline at end of file diff --git a/src/app/operational-view/operational-view-app-actions/OperationalViewAppActionsComponent.ts b/src/app/operational-view/operational-view-app-actions/OperationalViewAppActionsComponent.ts new file mode 100644 index 0000000..5a4f48e --- /dev/null +++ b/src/app/operational-view/operational-view-app-actions/OperationalViewAppActionsComponent.ts @@ -0,0 +1,67 @@ +/* + Copyright 2020 TATA ELXSI + + 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. + + Author: BARATH KUMAR R (barath.r@tataelxsi.co.in) +*/ + +/** + * @file Page for Operational View App actions Component + */ +import { Component, Injector, Input, OnInit } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { URLPARAMS } from 'CommonModel'; +import { isNullOrUndefined } from 'util'; +/** + * Creating component + * @Component takes OperationalViewAppActionsComponent.html as template url + */ +@Component({ + selector: 'app-operational-view-app-actions', + templateUrl: './OperationalViewAppActionsComponent.html' +}) +/** Exporting a class @exports OperationalViewAppActionsComponent */ +export class OperationalViewAppActionsComponent implements OnInit { + /** Invoke service injectors @public */ + public injector: Injector; + + /** Get the actions data @public */ + public actionsData: {}[]; + + /** Instance for active modal service @public */ + public activeModal: NgbActiveModal; + + /** Input contains component objects @private */ + @Input() private params: URLPARAMS; + + /** creates Operational view app actions component */ + constructor(injector: Injector) { + this.injector = injector; + this.activeModal = this.injector.get(NgbActiveModal); + } + + /** + * Lifecyle Hooks the trigger before component is instantiate + */ + public ngOnInit(): void { + this.actionsData = []; + if (!isNullOrUndefined(this.params.actions)) { + this.actionsData = Object.keys(this.params.actions).map((key: string): Object => ( + { + actions: key, + description: this.params.actions[key] + })); + } + } +} diff --git a/src/app/operational-view/operational-view-app-configs/OperationalViewAppConfigsComponent.html b/src/app/operational-view/operational-view-app-configs/OperationalViewAppConfigsComponent.html new file mode 100644 index 0000000..95264f6 --- /dev/null +++ b/src/app/operational-view/operational-view-app-configs/OperationalViewAppConfigsComponent.html @@ -0,0 +1,50 @@ + + + + \ No newline at end of file diff --git a/src/app/operational-view/operational-view-app-configs/OperationalViewAppConfigsComponent.ts b/src/app/operational-view/operational-view-app-configs/OperationalViewAppConfigsComponent.ts new file mode 100644 index 0000000..1e1b453 --- /dev/null +++ b/src/app/operational-view/operational-view-app-configs/OperationalViewAppConfigsComponent.ts @@ -0,0 +1,71 @@ +/* + Copyright 2020 TATA ELXSI + + 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. + + Author: BARATH KUMAR R (barath.r@tataelxsi.co.in) +*/ + +/** + * @file Page for Operational View App configs Component + */ +import { Component, Injector, Input, OnInit } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { URLPARAMS } from 'CommonModel'; +import { isNullOrUndefined } from 'util'; +/** + * Creating component + * @Component takes OperationalViewAppConfigsComponent.html as template url + */ +@Component({ + selector: 'app-operational-view-app-configs', + templateUrl: './OperationalViewAppConfigsComponent.html' +}) +/** Exporting a class @exports OperationalViewAppConfigsComponent */ +export class OperationalViewAppConfigsComponent implements OnInit { + /** Invoke service injectors @public */ + public injector: Injector; + + /** Get the config data @public */ + public configData: {}[]; + + /** Instance for active modal service @public */ + public activeModal: NgbActiveModal; + + /** Input contains component objects @private */ + @Input() private params: URLPARAMS; + + /** creates Operational view app config component */ + constructor(injector: Injector) { + this.injector = injector; + this.activeModal = this.injector.get(NgbActiveModal); + } + + /** + * Lifecyle Hooks the trigger before component is instantiate + */ + public ngOnInit(): void { + this.configData = []; + if (!isNullOrUndefined(this.params.configs)) { + this.configData = Object.keys(this.params.configs).map((key: string): Object => ( + { + name: key, + default: this.params.configs[key].default, + description: this.params.configs[key].description, + source: this.params.configs[key].source, + type: this.params.configs[key].type, + value: this.params.configs[key].value + })); + } + } +} diff --git a/src/app/operational-view/operational-view-app-executed-actions/OperationalViewAppExecutedActionsComponent.html b/src/app/operational-view/operational-view-app-executed-actions/OperationalViewAppExecutedActionsComponent.html new file mode 100644 index 0000000..65323b9 --- /dev/null +++ b/src/app/operational-view/operational-view-app-executed-actions/OperationalViewAppExecutedActionsComponent.html @@ -0,0 +1,53 @@ + + + + \ No newline at end of file diff --git a/src/app/operational-view/operational-view-app-executed-actions/OperationalViewAppExecutedActionsComponent.ts b/src/app/operational-view/operational-view-app-executed-actions/OperationalViewAppExecutedActionsComponent.ts new file mode 100644 index 0000000..af39f79 --- /dev/null +++ b/src/app/operational-view/operational-view-app-executed-actions/OperationalViewAppExecutedActionsComponent.ts @@ -0,0 +1,69 @@ +/* + Copyright 2020 TATA ELXSI + + 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. + + Author: BARATH KUMAR R (barath.r@tataelxsi.co.in) +*/ + +/** + * @file Page for Operational View App Executed actions Component + */ +import { Component, Injector, Input, OnInit } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { URLPARAMS } from 'CommonModel'; +import { EXECUTEDACTIONS } from 'OperationalModel'; +import { isNullOrUndefined } from 'util'; +/** + * Creating component + * @Component takes OperationalViewAppExecutedActionsComponent.html as template url + */ +@Component({ + selector: 'app-operational-view-executed-app-actions', + templateUrl: './OperationalViewAppExecutedActionsComponent.html' +}) +/** Exporting a class @exports OperationalViewAppExecutedActionsComponent */ +export class OperationalViewAppExecutedActionsComponent implements OnInit { + /** Invoke service injectors @public */ + public injector: Injector; + + /** Get the Executed actions data @public */ + public executedActionsData: EXECUTEDACTIONS[]; + + /** Instance for active modal service @public */ + public activeModal: NgbActiveModal; + + /** Is executed action not available @public */ + public isExecutedActionNotAvailable: boolean = false; + + /** Input contains component objects @private */ + @Input() private params: URLPARAMS; + + /** creates Operational view app executed actions component */ + constructor(injector: Injector) { + this.injector = injector; + this.activeModal = this.injector.get(NgbActiveModal); + } + + /** + * Lifecyle Hooks the trigger before component is instantiate + */ + public ngOnInit(): void { + if (!isNullOrUndefined(this.params.executedActions) && this.params.executedActions.length > 0) { + this.params.executedActions.sort((a: EXECUTEDACTIONS, b: EXECUTEDACTIONS): number => (+a.id > +b.id ? 1 : +a.id < +b.id ? -1 : 0)); + this.executedActionsData = this.params.executedActions; + } else { + this.isExecutedActionNotAvailable = true; + } + } +} diff --git a/src/app/utilities/ns-instances-action/NSInstancesActionComponent.html b/src/app/utilities/ns-instances-action/NSInstancesActionComponent.html index 977a87e..8a32bb7 100644 --- a/src/app/utilities/ns-instances-action/NSInstancesActionComponent.html +++ b/src/app/utilities/ns-instances-action/NSInstancesActionComponent.html @@ -16,6 +16,9 @@ limitations under the License. Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in) -->
+ diff --git a/src/app/utilities/ns-instances-action/NSInstancesActionComponent.ts b/src/app/utilities/ns-instances-action/NSInstancesActionComponent.ts index ed24a67..a66f78a 100644 --- a/src/app/utilities/ns-instances-action/NSInstancesActionComponent.ts +++ b/src/app/utilities/ns-instances-action/NSInstancesActionComponent.ts @@ -77,15 +77,18 @@ export class NSInstancesActionComponent { /** Assign the VNF Details @public */ public vnfDetails: VNFD[] = []; + /** Contains instance ID @public */ + public instanceID: string; + + /** Contains operational dashboard view @public */ + public isShowOperationalDashboard: boolean = false; + /** Instance of the modal service @private */ private modalService: NgbModal; /** Holds teh instance of AuthService class of type AuthService @private */ private router: Router; - /** Contains instance ID @private */ - private instanceID: string; - /** Contains all methods related to shared @private */ private sharedService: SharedService; @@ -120,6 +123,8 @@ export class NSInstancesActionComponent { this.operationalStatus = this.value.OperationalStatus; this.instanceID = this.value.identifier; this.getAdminDetails = this.value.adminDetails; + this.isShowOperationalDashboard = !isNullOrUndefined(this.value.vcaStatus) ? + Object.keys(this.value.vcaStatus).length === 0 && typeof this.value.vcaStatus === 'object' : true; } /** Shows information using modalservice @public */ diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 8e24408..5d67b03 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -140,6 +140,7 @@ "SUBMIT": "Submit", "REFRESH": "Aktualisierung", "OPEN": "Öffnen", + "CLOSE": "Schließen", "UPLOADCONFIG": "Upload Config", "FILEUPLOADLABEL": "Oder aus Datei laden", "CONFIG": "Konfig", @@ -154,6 +155,16 @@ "SCALEIN": "Scale In", "SCALING": "Manuelle Skalierung", "SCALINGNOTFOUND": "scaling-aspect nicht in vnfd gefunden", + "NODATA": "Derzeit sind keine Daten verfügbar", + "STATUS": "Status", + "PUBLICADDRESS": "Öffentliche Adresse", + "EXECUTEDACTIONS": "Ausgeführte Aktionen", + "OUTPUT": "Ausgabe", + "VERIFIED": "Verifiziert", + "CODE": "Code", + "SCALE": "Rahmen", + "DEFAULT": "Standard", + "SOURCE": "Quelle", "PAGE": { "DASHBOARD": { "DASHBOARD": "Instrumententafel", @@ -429,6 +440,36 @@ "OSMREPOTITLE": "Registriertes OSM-Repository", "CREATEDSUCCESSFULLY": "OSM-Repository erfolgreich hinzugefügt", "UPDATEDSUCCESSFULLY": "OSM-Repository erfolgreich aktualisiert" + }, + "OPERATIONALDASHBOARD": { + "TITLE": "Betriebs-Dashboard", + "MODELSUMMARY": "Modellzusammenfassung", + "MODEL": "Modell", + "APPLICATION": "App", + "APPLICATIONTITLE": "Apps", + "UNITS": "Einheit", + "UNITSTITLE": "Einheiten", + "RELATIONS": "Beziehungen", + "NOAPPLICATION": "Es gibt keine Anwendung in diesem Modell", + "NOUNITS": "Es gibt keine Einheiten in diesem Modell", + "NORELATIONS": "In diesem Modell gibt es keine Beziehungen", + "NOMACHINES": "Es gibt keine Maschinen in diesem Modell", + "NOEXECUTEDACTIONS": "In diesem Modell sind keine Aktionen ausgeführt", + "MACHINE": "Maschine", + "MACHINETITLE": "Maschinen", + "MESSAGE": "Botschaft", + "WORKLOAD": "Arbeitsbelastung", + "AGENT": "Agent", + "ADDRESS": "Adresse", + "INTERFACE": "Interface", + "REQUIRER": "Requerente", + "RELATIONPROVIDER": "Provedor de relacionamento", + "CHARM": "Charm", + "STORE": "Loja", + "LEADER": "Führer", + "LIVELOAD": "Live-Laden", + "SETSECONDS": "Timer einstellen", + "SERIES": "Serie" } }, "HTTPERROR": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 11cbc54..c412e15 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -140,6 +140,7 @@ "SUBMIT": "Submit", "REFRESH": "Refresh", "OPEN": "Open", + "CLOSE": "Close", "UPLOADCONFIG": "Upload Config", "FILEUPLOADLABEL": "Or load from file", "CONFIG": "Config", @@ -154,6 +155,16 @@ "SCALEIN": "Scale In", "SCALING": "Manual Scaling", "SCALINGNOTFOUND": "scaling-aspect not found in vnfd", + "NODATA": "Currently data not available", + "STATUS": "Status", + "PUBLICADDRESS": "Public Address", + "EXECUTEDACTIONS": "Executed Actions", + "OUTPUT": "Output", + "VERIFIED": "Verified", + "CODE": "Code", + "SCALE": "Scale", + "DEFAULT": "Default", + "SOURCE": "Source", "PAGE": { "DASHBOARD": { "DASHBOARD": "Dashboard", @@ -429,6 +440,36 @@ "OSMREPOTITLE": "Registered OSM repository", "CREATEDSUCCESSFULLY": "OSM Repository Added Successfully", "UPDATEDSUCCESSFULLY": "OSM Repository Updated Successfully" + }, + "OPERATIONALDASHBOARD": { + "TITLE": "Operational Dashboard", + "MODELSUMMARY": "Model Summary", + "MODEL": "Model", + "APPLICATION": "App", + "APPLICATIONTITLE": "Apps", + "UNITS": "Unit", + "UNITSTITLE": "Units", + "RELATIONS": "Relations", + "NOAPPLICATION": "There are no application in this model", + "NOUNITS": "There are no units in this model", + "NORELATIONS": "There are no relations in this model", + "NOMACHINES": "There are no machines in this model", + "NOEXECUTEDACTIONS": "There are no executed actions in this model", + "MACHINE": "Machine", + "MACHINETITLE": "Machines", + "MESSAGE": "Message", + "WORKLOAD": "Workload", + "AGENT": "Agent", + "ADDRESS": "Address", + "INTERFACE": "Interface", + "REQUIRER": "Requirer", + "RELATIONPROVIDER": "Relation Provider", + "CHARM": "Charm", + "STORE": "Store", + "LEADER": "Leader", + "LIVELOAD": "Live Loading", + "SETSECONDS": "Set Timer", + "SERIES": "Series" } }, "HTTPERROR": { diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index a74a931..55c9490 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -139,7 +139,8 @@ "CURRENTPROJECT": "Proyecto actual", "SUBMIT": "Entrar", "REFRESH": "Actualizar", - "OPEN": "Abierto", + "OPEN": "Abrir", + "CLOSE": "Cerrar", "UPLOADCONFIG": "Subir configuración", "FILEUPLOADLABEL": "O cargar desde el archivo", "CONFIG": "Config", @@ -154,6 +155,16 @@ "SCALEIN": "Escalar", "SCALING": "Escalado manual", "SCALINGNOTFOUND": "scaling-aspect no encontrado en vnfd", + "NODATA": "Actualmente datos no disponibles", + "STATUS": "Estado", + "PUBLICADDRESS": "Dirección pública", + "EXECUTEDACTIONS": "Acciones ejecutadas", + "OUTPUT": "Salida", + "VERIFIED": "Verificada", + "CODE": "Código", + "SCALE": "Escala", + "DEFAULT": "por defecto", + "SOURCE": "Fuente", "PAGE": { "DASHBOARD": { "DASHBOARD": "Tablero", @@ -429,6 +440,36 @@ "OSMREPOTITLE": "Repositorio OSM registrado", "CREATEDSUCCESSFULLY": "Repositorio OSM agregado correctamente", "UPDATEDSUCCESSFULLY" : "Repositorio OSM actualizado correctamente" + }, + "OPERATIONALDASHBOARD": { + "TITLE": "Tablero operativo", + "MODELSUMMARY": "Resumen de modelo", + "MODEL": "Modelo", + "APPLICATION": "App", + "APPLICATIONTITLE": "Apps", + "UNITS": "Unidad", + "UNITSTITLE": "Unidades", + "RELATIONS": "Relaciones", + "NOAPPLICATION": "No hay aplicación en este modelo.", + "NOUNITS": "No hay unidades en este modelo", + "NORELATIONS": "No hay relaciones en este modelo.", + "NOMACHINES": "No hay máquinas en este modelo.", + "NOEXECUTEDACTIONS": "No hay acciones ejecutadas en este modelo", + "MACHINE": "Máquina", + "MACHINETITLE": "Máquinas", + "MESSAGE": "Mensaje", + "WORKLOAD": "Carga de trabajo", + "AGENT": "Agente", + "ADDRESS": "Dirección", + "INTERFACE": "Interfaz", + "REQUIRER": "Solicitante", + "RELATIONPROVIDER": "Proveedor de relaciones", + "CHARM": "Charm", + "STORE": "Tienda", + "LEADER": "Líder", + "LIVELOAD": "Cargando en vivo", + "SETSECONDS": "Configurar temporizador", + "SERIES": "serie" } }, "HTTPERROR": { diff --git a/src/assets/i18n/pt.json b/src/assets/i18n/pt.json index d4ebbfc..b0f7985 100644 --- a/src/assets/i18n/pt.json +++ b/src/assets/i18n/pt.json @@ -140,6 +140,7 @@ "SUBMIT": "Enviar", "REFRESH": "Atualizar", "OPEN": "Aberto", + "CLOSE": "Fechar", "UPLOADCONFIG": "Upload Config", "FILEUPLOADLABEL": "Ou carregue do arquivo", "CONFIG": "Config", @@ -154,6 +155,16 @@ "SCALEIN": "Escala em", "SCALING": "Escalonamento Manual", "SCALINGNOTFOUND": "scaling-aspect não encontrado no vnfd", + "NODATA": "Atualmente, os dados não estão disponíveis", + "STATUS": "Status", + "PUBLICADDRESS": "Endereço público", + "EXECUTEDACTIONS": "Ações Executadas", + "OUTPUT": "Resultado", + "VERIFIED": "Verificada", + "CODE": "Code", + "SCALE": "Escala", + "DEFAULT": "Padrão", + "SOURCE": "Fonte", "PAGE": { "DASHBOARD": { "DASHBOARD": "painel de controle", @@ -429,6 +440,36 @@ "OSMREPOTITLE": "Repositório OSM registrado", "CREATEDSUCCESSFULLY": "registrado OSM adicionado com sucesso", "UPDATEDSUCCESSFULLY": "registrado OSM atualizado com sucesso" + }, + "OPERATIONALDASHBOARD": { + "TITLE": "Painel Operacional", + "MODELSUMMARY": "Resumo do modelo", + "MODEL": "Modelo", + "APPLICATION": "App", + "APPLICATIONTITLE": "Apps", + "UNITS": "Unidade", + "UNITSTITLE": "Unidades", + "RELATIONS": "Relações", + "NOAPPLICATION": "Não há aplicação neste modelo", + "NOUNITS": "Não há unidades neste modelo", + "NORELATIONS": "Não há relações neste modelo", + "NOMACHINES": "Não há máquinas neste modelo", + "NOEXECUTEDACTIONS": "Não há ações executadas neste modelo", + "MACHINE": "Máquina", + "MACHINETITLE": "Maquinas", + "MESSAGE": "mensagem", + "WORKLOAD": "Carga de trabalho", + "AGENT": "Agente", + "ADDRESS": "Endereço", + "INTERFACE": "Interface", + "REQUIRER": "Requerente", + "RELATIONPROVIDER": "Provedor de relacionamento", + "CHARM": "Charm", + "STORE": "Loja", + "LEADER": "Líder", + "LIVELOAD": "Carregando ao vivo", + "SETSECONDS": "Definir temporizador", + "SERIES": "Series" } }, "HTTPERROR": { diff --git a/src/assets/scss/app.scss b/src/assets/scss/app.scss index 38318a7..8dd8399 100644 --- a/src/assets/scss/app.scss +++ b/src/assets/scss/app.scss @@ -128,9 +128,6 @@ body { color: $gray-400; } } - .modal-dialog { - max-width: 600px; - } .header-style { @include font(null, 1.2rem, 700); color: $primary; @@ -182,6 +179,37 @@ body { } } } + .juju-section { + .card { + @include roundedCorners(4); + margin-bottom: 0.25rem; + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + .bg-secondary { + @include background(null, $primary !important, null, null, null); + b, + span { + color: $white; + } + } + .card-body { + .seconds-btn-group .active { + color: $white; + @include background(null, $primary !important, null, null, null); + } + @include border(all, 2, dashed, $primary); + @include padding-value(5, 5, 5, 5); + border-top: 0; + table { + thead th { + font-size: 12px; + } + tbody th i.active-icon { + font-size: 10px; + } + } + } + } + } .card { margin-bottom: 1rem; } @@ -694,6 +722,93 @@ body { } } } + /** Switch Design **/ + .switch { + @include position_value(relative, null, null, null, null); + @include flexbox(inline-block, null, null, null, null, null); + @include wh-value(50px, 15px); + @include margin-value(0, 0, 0, 0); + input { + opacity: 0; + @include wh-value(0px, 0px); + &:checked + .slider { + @include background(null, $gray-400, null, null, null); + &:before { + @include background(null, $pure-red, null, null, null); + left: 5px; + animation: pulse 2s infinite; + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); + } + .on { + @include flexbox(block, null, null, null, null, null); + } + .off { + @include flexbox(none, null, null, null, null, null); + } + } + } + .slider { + @include position_value(absolute, 0, 0, 0, 0); + cursor: pointer; + @include background(null, $gray-400, null, null, null); + -webkit-transition: 0.4s; + transition: 0.4s; + box-shadow: 0 0 1px $gray-400; + &.round { + @include roundedCorners(30); + &:before { + @include roundedCornersPercentage(50%); + } + } + &:before { + @include position_value(absolute, null, null, -2px, 0px); + @include wh-value(20px, 20px); + @include background(null, $white, null, null, null); + content: ""; + -webkit-transition: 0.4s; + transition: 0.4s; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); + } + .on { + @include flexbox(none, null, null, null, null, null); + @include position_value(absolute, 50%, null, null, 35% !important); + } + .on, + .off { + @include position_value(absolute, 50%, null, null, 65%); + color: $primary; + transform: translate(-50%, -50%); + @include font(null, 11px, bold); + } + } + @-webkit-keyframes pulse { + 0% { + -webkit-box-shadow: 0 0 0 0 rgba(204, 89, 44, 0.4); + } + 70% { + -webkit-box-shadow: 0 0 0 10px rgba(204, 89, 44, 0); + } + 100% { + -webkit-box-shadow: 0 0 0 0 rgba(204, 89, 44, 0); + } + } + @keyframes pulse { + 0% { + -moz-box-shadow: 0 0 0 0 rgba(204, 89, 44, 0.4); + box-shadow: 0 0 0 0 rgba(204, 89, 44, 0.4); + } + 70% { + -moz-box-shadow: 0 0 0 10px rgba(204, 89, 44, 0); + box-shadow: 0 0 0 10px rgba(204, 89, 44, 0); + } + 100% { + -moz-box-shadow: 0 0 0 0 rgba(204, 89, 44, 0); + box-shadow: 0 0 0 0 rgba(204, 89, 44, 0); + } + } + } } /****************************************************************************/ /************************** MEDIA QUERIES ***********************************/ @@ -709,6 +824,25 @@ body { .text-captilize { text-transform: capitalize; } -.text-info{ +.text-info { color: $secondary !important; } +.hide { + @include flexbox(none, null, null, null, null, null); +} +.title-bar { + .name-width { + @include wh-value(20%, null); + } + .id-width { + @include wh-value(25%, null); + } +} +.filter-actions { + button { + @include roundedCorners(10); + @include padding-percentage-value(0.2rem, 1rem, 0.2rem, 1rem); + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + border: none; + } +} diff --git a/src/models/CommonModel.ts b/src/models/CommonModel.ts index 7bd1cca..7b51e9e 100644 --- a/src/models/CommonModel.ts +++ b/src/models/CommonModel.ts @@ -17,6 +17,7 @@ */ import { HttpHeaders } from '@angular/common/http'; import { NSD } from 'NSInstanceModel'; +import { EXECUTEDACTIONS } from 'OperationalModel'; import { VNFD } from 'VNFDModel'; /** @@ -41,7 +42,8 @@ export enum CONSTANTNUMBER { oneMB = 1048576, paginationDefaultValue = 10, splitLongitude = 1, - splitLatitude = 2 + splitLatitude = 2, + timeOutDefaultSeconds = 5 } /** * handle count @enum @@ -115,6 +117,9 @@ export interface URLPARAMS { nsID?: string; nsd?: NSD; data?: VNFD[]; + configs?: object; + actions?: object; + executedActions?: EXECUTEDACTIONS[]; } /** Handle the Delete params */ export interface DELETEPARAMS { diff --git a/src/models/MenuModel.ts b/src/models/MenuModel.ts index deb9654..d9d0620 100644 --- a/src/models/MenuModel.ts +++ b/src/models/MenuModel.ts @@ -134,6 +134,16 @@ export const MENU_ITEMS: MENUITEMS[] = [ icon: 'fas fa-layer-group', menuName: 'PAGE.DASHBOARD.NETSLICEINSTANCE', isChildExists: false + }, + { + liClass: '', + anchorTagClass: 'link', + routerLink: '/instances/operational-view', + routerLinkActive: childActiveClass, + routerLinkActiveOptions: false, + icon: 'fas fa-tachometer-alt', + menuName: 'PAGE.OPERATIONALDASHBOARD.TITLE', + isChildExists: false } ] }, diff --git a/src/models/NSInstanceModel.ts b/src/models/NSInstanceModel.ts index ce44122..62b9c5c 100644 --- a/src/models/NSInstanceModel.ts +++ b/src/models/NSInstanceModel.ts @@ -48,6 +48,7 @@ export interface NSInstanceDetails { instantiate_params: InstantiateParam; additionalParamsForNs: AdditionalParamForN; _id?: string; + vcaStatus?: object; } /** Interface for Admin */ @@ -179,6 +180,7 @@ export interface NSDInstanceData { state?: string; memberIndex?: DF[]; nsConfig?: object; + vcaStatus?: object; adminDetails?: object; vnfID?: string[]; nsd?: NSD; diff --git a/src/models/OperationalModel.ts b/src/models/OperationalModel.ts new file mode 100644 index 0000000..79f248e --- /dev/null +++ b/src/models/OperationalModel.ts @@ -0,0 +1,147 @@ +/* + Copyright 2020 TATA ELXSI + + 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. + + Author: BARATH KUMAR R (barath.r@tataelxsi.co.in) + */ + +/** + * @file Model for Operational view JUJU information. + */ + +// tslint:disable: completed-docs + +/** Interface for the VCASTATUS */ +export interface VCASTATUS { + vcaStatus: VCADETAILS; + name: string; + id: string; +} +/** Interface for the VCASTATUS */ +export interface VCADETAILS { + isLiveloading: boolean; + ns_id: string; + vcaStatusModels: SETMODELS[]; + timeOutSeconds?: number; + vca_id: string; + vca_name: string; +} +/** Interface for the SETMODELS */ +export interface SETMODELS { + applications: VCAAPPLICATIONS[]; + branches?: {}; + controller_timestamp?: string; + executedActions?: EXECUTEDACTIONS; + machines: MACHINES[]; + model: VCAMODEL; + offers?: {}; + relations: RELATIONS[]; + remote_applications?: {}; + units: VCAUNITS[]; + unknown_fields?: {}; +} +/** Interface for the VCAAPPLICATIONS */ +export interface VCAAPPLICATIONS { + app_id: string; + charm: string; + store: string; + units: {}; + status: STATUS; + scale: number; + public_address: string; + agent_status: AGENTSTATUS; + configs: object; + actions: object; +} +/** Interface for the VCAUNITS */ +export interface VCAUNITS { + address: string; + machine: string; + unit_id: string; + public_address: string; + status: string; + agent_status: AGENTSTATUS; +} +/** Interface for the EXECUTEDACTIONS */ +export interface EXECUTEDACTIONS { + id: string; + action: string; + status: string; + Code: string; + outout: string; + verified: string; +} +/** Interface for the VCAMODEL */ +export interface VCAMODEL { + available_version: string; + cloud_tag: string; + migration: string; + name: string; + region: string; + version: string; +} +/** Interface for the STATUS */ +export interface STATUS { + status: string; +} +/** Interface for the AGENTSTATUS */ +export interface AGENTSTATUS { + status: string; + info?: string; +} +/** Interface for the MACHINES */ +export interface MACHINES { + id_: string; + agent_status: AGENTSTATUS; + dns_name: string; + instance_id: string; + series: string; + instance_status: AGENTSTATUS; +} +/** Interface for the RELATIONS */ +export interface RELATIONS { + endpoints: ENDPOINTS[]; + 'interface': string; + key: string; +} +/** Interface for the ENDPOINTS */ +export interface ENDPOINTS { + application: string; + name: string; + role: string; + subordinate: string; +} +/** Interface for the SETTIMER */ +export interface SETTIMER { + label: string; + value: number; +} +export const SET_TIMER: SETTIMER[] = [ + { + label: '5s', + value: 5 + }, + { + label: '10s', + value: 10 + }, + { + label: '30s', + value: 30 + }, + { + label: '1m', + value: 60 + } +]; diff --git a/tsconfig.json b/tsconfig.json index 6397742..7c024ea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -142,7 +142,12 @@ "OsmRepositoriesAction" : ["src/app/utilities/osm-repositories-action/OsmRepositoriesActionComponent"], "OsmRepoModel": ["src/models/OsmRepoModel"], "OsmRepoCreateUpdate": ["src/app/osm-repositories/osm-repo-create-update/OsmRepoCreateUpdateComponent"], - "ScalingComponent": ["src/app/utilities/scaling/ScalingComponent"] + "ScalingComponent": ["src/app/utilities/scaling/ScalingComponent"], + "OperationalViewComponent": ["src/app/operational-view/OperationalViewComponent"], + "OperationalModel": ["src/models/OperationalModel"], + "OperationalAppConfigsComponent": ["src/app/operational-view/operational-view-app-configs/OperationalViewAppConfigsComponent"], + "OperationalAppActionsComponent": ["src/app/operational-view/operational-view-app-actions/OperationalViewAppActionsComponent"], + "OperationalAppExecutedActionsComponent" : ["src/app/operational-view/operational-view-app-executed-actions/OperationalViewAppExecutedActionsComponent"] } } } \ No newline at end of file