RIC Dashboard Release Notes
===========================
-Version 1.2.0, 11 July 2019
+Version 1.2.0, 12 July 2019
---------------------------
* Split URL properties into prefix/suffix parts
* Add jacoco plugin to back-end for code coverage
* Compile with Java version 11, run with image openjdk:11
* Clean code of issues reported by Sonar
* Drop mock RAN names feature that supported R1 testing
+* Extend mock endpoints to simulate delay seen in tests
Version 1.0.5, 5 July 2019
--------------------------
public class A1MediatorMockConfiguration {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ // Simulate remote method delay for UI testing
+ private final int delayMs = 500;
public A1MediatorMockConfiguration() {
logger.info("Configuring mock A1 Mediator");
ApiClient apiClient = apiClient();
A1MediatorApi mockApi = mock(A1MediatorApi.class);
when(mockApi.getApiClient()).thenReturn(apiClient);
- doAnswer(i -> null).when(mockApi).a1ControllerGetHandler(any(String.class));
- doAnswer(i -> null).when(mockApi).a1ControllerPutHandler(any(String.class), any(Object.class));
+ doAnswer(inv -> {
+ logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).a1ControllerGetHandler(any(String.class));
+ doAnswer(inv -> {
+ logger.debug("a1ControllerPutHandler sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).a1ControllerPutHandler(any(String.class), any(Object.class));
return mockApi;
}
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private static final String GNODEB1 = "001EF5:0045FE50";
+ private static final String GNODEB2 = "001EF6:0045FE51";
+ private static final String GNODEB3 = "001EF7:0045FE52";
// Sonar wants separate declarations
private final NeighborCellRelationTable ncrt;
private final NeighborCellRelationTable ncrtNodeB1;
private final NeighborCellRelationTable ncrtNodeB2;
private final NeighborCellRelationTable ncrtNodeB3;
-
private final GgNodeBTable gNodebTable;
-
- private static final String GNODEB1 = "001EF5:0045FE50";
- private static final String GNODEB2 = "001EF6:0045FE51";
- private static final String GNODEB3 = "001EF7:0045FE52";
+ // Simulate remote method delay for UI testing
+ private final int delayMs = 500;
public AnrXappMockConfiguration() {
-
logger.info("Configuring mock ANR xApp client");
gNodebTable = new GgNodeBTable();
gNodebTable.addGNodeBIdsItem(GNODEB1).addGNodeBIdsItem(GNODEB2).addGNodeBIdsItem(GNODEB3);
ApiClient apiClient = apiClient();
NcrtApi mockApi = mock(NcrtApi.class);
when(mockApi.getApiClient()).thenReturn(apiClient);
- when(mockApi.getgNodeB()).thenReturn(gNodebTable);
+ doAnswer(inv -> {
+ logger.debug("getgNodeB sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return gNodebTable;
+ }).when(mockApi).getgNodeB();
// Swagger sends nulls; front end sends empty strings
- when(mockApi.getNcrt((String) isNull(), (String) isNull(), (String) isNull())).thenReturn(ncrt);
- when(mockApi.getNcrt(eq(""), any(String.class), any(String.class))).thenReturn(ncrt);
- when(mockApi.getNcrt(eq(GNODEB1), any(String.class), any(String.class))).thenReturn(ncrtNodeB1);
- when(mockApi.getNcrt(eq(GNODEB2), any(String.class), any(String.class))).thenReturn(ncrtNodeB2);
- when(mockApi.getNcrt(eq(GNODEB3), any(String.class), any(String.class))).thenReturn(ncrtNodeB3);
- doAnswer(i -> null).when(mockApi).deleteNcrt(any(String.class), any(String.class));
- doAnswer(i -> null).when(mockApi).modifyNcrt(any(String.class), any(String.class),
- any(NeighborCellRelationMod.class));
+ doAnswer(inv -> {
+ logger.debug("getNcrt (1) sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return ncrt;
+ }).when(mockApi).getNcrt((String) isNull(), (String) isNull(), (String) isNull());
+ doAnswer(inv -> {
+ logger.debug("getNcrt (2) sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return ncrt;
+ }).when(mockApi).getNcrt(eq(""), any(String.class), any(String.class));
+ doAnswer(inv -> {
+ logger.debug("getNcrt (3) sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return ncrtNodeB1;
+ }).when(mockApi).getNcrt(eq(GNODEB1), any(String.class), any(String.class));
+ doAnswer(inv -> {
+ logger.debug("getNcrt (4) sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return ncrtNodeB2;
+ }).when(mockApi).getNcrt(eq(GNODEB2), any(String.class), any(String.class));
+ doAnswer(inv -> {
+ logger.debug("getNcrt (5) sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return ncrtNodeB3;
+ }).when(mockApi).getNcrt(eq(GNODEB3), any(String.class), any(String.class));
+ doAnswer(inv -> {
+ logger.debug("deleteNcrt sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).deleteNcrt(any(String.class), any(String.class));
+ doAnswer(inv -> {
+ logger.debug("modifyNcrt sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).modifyNcrt(any(String.class), any(String.class), any(NeighborCellRelationMod.class));
return mockApi;
}
private final AllDeployableXapps availXapps;
private final AllDeployedXapps deployedXapps;
private final AllXappConfig allXappConfigs;
+ private final SubscriptionResponse subRes;
+ // Simulate remote method delay for UI testing
+ private final int delayMs = 500;
public AppManagerMockConfiguration() {
logger.info("Configuring mock xApp Manager");
.status(XappInstance.StatusEnum.RUNNING));
deployedXapps.add(xapp);
}
+ subRes = new SubscriptionResponse().eventType(SubscriptionResponse.EventTypeEnum.ALL).id("subid").version(1);
}
@Bean
when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
XappApi mockApi = mock(XappApi.class);
when(mockApi.getApiClient()).thenReturn(mockClient);
- when(mockApi.getAllXappConfig()).thenReturn(allXappConfigs);
- when(mockApi.createXappConfig(any(XAppConfig.class))).thenReturn(allXappConfigs.get(0));
- when(mockApi.modifyXappConfig(any(XAppConfig.class))).thenReturn(allXappConfigs.get(0));
- doAnswer(i -> null).when(mockApi).deleteXappConfig(any(ConfigMetadata.class));
- when(mockApi.deployXapp(any(XAppInfo.class))).thenReturn(deployedXapps.get(0));
- when(mockApi.listAllXapps()).thenReturn(availXapps);
- when(mockApi.getAllXapps()).thenReturn(deployedXapps);
- when(mockApi.getXappByName(any(String.class))).thenReturn(deployedXapps.get(0));
- doAnswer(i -> null).when(mockApi).undeployXapp(any(String.class));
- SubscriptionResponse subRes = new SubscriptionResponse().eventType(SubscriptionResponse.EventTypeEnum.ALL)
- .id("subid").version(1);
- when(mockApi.addSubscription(any(SubscriptionRequest.class))).thenReturn(subRes);
- doAnswer(i -> null).when(mockApi).deleteSubscription(any(String.class));
+ doAnswer(inv -> {
+ logger.debug("getAllXappConfig sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return allXappConfigs;
+ }).when(mockApi).getAllXappConfig();
+ doAnswer(inv -> {
+ logger.debug("createXappConfig sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return allXappConfigs.get(0);
+ }).when(mockApi).createXappConfig(any(XAppConfig.class));
+ doAnswer(inv -> {
+ logger.debug("modifyXappConfig sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return allXappConfigs.get(0);
+ }).when(mockApi).modifyXappConfig(any(XAppConfig.class));
+ doAnswer(inv -> {
+ logger.debug("deleteXappConfig sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).deleteXappConfig(any(ConfigMetadata.class));
+ doAnswer(inv -> {
+ logger.debug("deployXapp of {} sleeping {}", inv.getArgument(0), delayMs);
+ Thread.sleep(delayMs);
+ return deployedXapps.get(0);
+ }).when(mockApi).deployXapp(any(XAppInfo.class));
+ doAnswer(inv -> {
+ logger.debug("listAllXapps sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return availXapps;
+ }).when(mockApi).listAllXapps();
+ doAnswer(inv -> {
+ logger.debug("getAllXapps sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return deployedXapps;
+ }).when(mockApi).getAllXapps();
+ doAnswer(inv -> {
+ logger.debug("getXappByName of {} sleeping {}", inv.getArgument(0), delayMs);
+ Thread.sleep(delayMs);
+ return deployedXapps.get(0);
+ }).when(mockApi).getXappByName(any(String.class));
+ doAnswer(inv -> {
+ logger.debug("undeployXapp of {} sleeping {}", inv.getArgument(0), delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).undeployXapp(any(String.class));
+ doAnswer(inv -> {
+ logger.debug("addSubscription sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return subRes;
+ }).when(mockApi).addSubscription(any(SubscriptionRequest.class));
+ doAnswer(inv -> {
+ logger.debug("deleteSubscription sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).deleteSubscription(any(String.class));
return mockApi;
}
private final List<NodebIdentity> nodebIdList;
private final GetNodebResponse nodebResponse;
+ // Simulate remote method delay for UI testing
+ private final int delayMs = 500;
public E2ManagerMockConfiguration() {
logger.info("Configuring mock E2 Manager");
ApiClient apiClient = apiClient();
NodebApi mockApi = mock(NodebApi.class);
when(mockApi.getApiClient()).thenReturn(apiClient);
- doAnswer(i -> null).when(mockApi).nodebDelete();
- doAnswer(i -> nodebResponse).when(mockApi).getNb(any(String.class));
- doAnswer(i -> nodebIdList).when(mockApi).getNodebIdList();
- doAnswer(i -> null).when(mockApi).endcSetup(any(SetupRequest.class));
- doAnswer(i -> null).when(mockApi).x2Setup(any(SetupRequest.class));
+ doAnswer(inv -> {
+ logger.debug("nodebDelete sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).nodebDelete();
+ doAnswer(inv -> {
+ logger.debug("getNb sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return nodebResponse;
+ }).when(mockApi).getNb(any(String.class));
+ doAnswer(inv -> {
+ logger.debug("getNodebIdList sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return nodebIdList;
+ }).when(mockApi).getNodebIdList();
+ doAnswer(inv -> {
+ logger.debug("endcSetup sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).endcSetup(any(SetupRequest.class));
+ doAnswer(inv -> {
+ logger.debug("x2Setup sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ return null;
+ }).when(mockApi).x2Setup(any(SetupRequest.class));
return mockApi;
}
*/
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
+import { HttpResponse } from '@angular/common/http';
import { MatSort } from '@angular/material';
import { MatDialog } from '@angular/material/dialog';
import { fromEvent } from 'rxjs/observable/fromEvent';
if (res) {
this.anrXappService.deleteNcr(ncr.servingCellNrcgi, ncr.neighborCellNrpci)
.subscribe(
- response => {
+ (response: HttpResponse<Object>) => {
switch (response.status) {
case 200:
this.notificationService.success('Delete succeeded!');
<button mat-icon-button (click)="controlApp(element)">
<mat-icon matTooltip="Adjust settings">settings</mat-icon>
</button>
- <button mat-icon-button (click)="undeployApp(element)">
+ <button mat-icon-button (click)="onUndeployApp(element)">
<mat-icon matTooltip="Undeploy app">cloud_download</mat-icon>
</button>
</mat-cell>
</table>
<div class="spinner-container" *ngIf="dataSource.loading$ | async">
- <mat-spinner></mat-spinner>
+ <mat-spinner diameter=50></mat-spinner>
</div>
</div>
* ========================LICENSE_END===================================
*/
import { Component, OnInit, ViewChild } from '@angular/core';
+import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { MatSort } from '@angular/material/sort';
import { Router } from '@angular/router';
import { XappControlRow } from '../interfaces/app-mgr.types';
}
}
- undeployApp(app: XappControlRow): void {
+ onUndeployApp(app: XappControlRow): void {
this.confirmDialogService.openConfirmDialog('Are you sure you want to undeploy xApp ' + app.xapp + '?')
- .afterClosed().subscribe(res => {
+ .afterClosed().subscribe( (res: boolean) => {
if (res) {
this.appMgrSvc.undeployXapp(app.xapp).subscribe(
- response => {
+ ( httpResponse: HttpResponse<Object>) => {
this.dataSource.loadTable();
- switch (response.status) {
+ switch (httpResponse.status) {
case 200:
this.notificationService.success('xApp undeployed successfully!');
break;
default:
this.notificationService.warn('xApp undeploy failed.');
}
- }
+ },
+ ( (error: HttpErrorResponse) => {
+ this.notificationService.warn(error.message);
+ })
);
}
});
<mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
<mat-cell *matCellDef="let element">
<div class="catalog-button-row">
- <button mat-icon-button (click)="onConfigureApp(element.name)">
+ <button mat-icon-button (click)="onConfigureApp(element)">
<mat-icon matTooltip="Adjust settings">settings</mat-icon>
</button>
- <button mat-icon-button (click)="onDeployApp(element.name)">
+ <button mat-icon-button (click)="onDeployApp(element)">
<mat-icon matTooltip="Deploy app">cloud_upload</mat-icon>
</button>
</div>
</table>
<div class="spinner-container" *ngIf="dataSource.loading$ | async">
- <mat-spinner></mat-spinner>
+ <mat-spinner diameter=50></mat-spinner>
</div>
</div>
background-color: transparent;
}
+.mat-column-action {
+ max-width: 200px;
+}
+
.catalog-button-row button{
margin-right: 5px;
}
import { ConfirmDialogService } from './../services/ui/confirm-dialog.service';
import { NotificationService } from './../services/ui/notification.service';
import { CatalogDataSource } from './catalog.datasource';
+import { XMDeployableApp } from '../interfaces/app-mgr.types';
@Component({
selector: 'rd-app-catalog',
this.errorDiaglogService.displayError(aboutError);
}
- onDeployApp(name: string): void {
- this.confirmDialogService.openConfirmDialog('Deploy application ' + name + '?')
- .afterClosed().subscribe( (res: any) => {
+ onDeployApp(app: XMDeployableApp): void {
+ this.confirmDialogService.openConfirmDialog('Deploy application ' + app.name + '?')
+ .afterClosed().subscribe( (res: boolean) => {
if (res) {
- this.appMgrService.deployXapp(name).subscribe(
- (response: HttpResponse<object>) => {
+ this.appMgrService.deployXapp(app.name).subscribe(
+ (response: HttpResponse<Object>) => {
this.notificationService.success('Deploy succeeded!');
},
(error: HttpErrorResponse) => {
export interface E2SetupRequest {
ranName: string;
ranIp: string;
- ranPort: number;
+ ranPort: string;
}
export interface E2ErrorResponse {
nodebIdentity: E2NodebIdentity;
nodebStatus: E2GetNodebResponse;
}
+
+export interface RanDialogFormData {
+ ranIp: string;
+ ranName: string;
+ ranPort: string;
+ ranType: string;
+}
<div mat-dialog-title>
Setup RAN Connection
</div>
-
<form [formGroup]="ranDialogForm" novalidate autocomplete="off" (ngSubmit)="setupConnection(ranDialogForm.value)">
<div mat-dialog-content>
<div name="rantype">
</div>
<div mat-dialog-actions class="modal-footer justify-content-center">
<button class="mat-raised-button" (click)="onCancel()">Cancel</button>
- <button class="mat-raised-button mat-primary" [disabled]="!ranDialogForm.valid">Connect</button>
+ <button class="mat-raised-button mat-primary" [disabled]="!ranDialogForm.valid || processing">Connect</button>
</div>
</form>
* ========================LICENSE_END===================================
*/
import { Component, OnInit, Inject } from '@angular/core';
+import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { Observable } from 'rxjs';
import { E2ManagerService } from '../services/e2-mgr/e2-mgr.service';
import { NotificationService } from '../services/ui/notification.service';
import { ErrorDialogService } from '../services/ui/error-dialog.service';
-import { E2SetupRequest } from '../interfaces/e2-mgr.types';
-import { HttpErrorResponse } from '@angular/common/http';
+import { E2SetupRequest, RanDialogFormData } from '../interfaces/e2-mgr.types';
@Component({
selector: 'rd-ran-control-connect-dialog',
export class RanControlConnectDialogComponent implements OnInit {
public ranDialogForm: FormGroup;
+ public processing = false;
constructor(
private dialogRef: MatDialogRef<RanControlConnectDialogComponent>,
private service: E2ManagerService,
private errorService: ErrorDialogService,
- private notifService: NotificationService,
- @Inject(MAT_DIALOG_DATA) public data: E2SetupRequest) {
+ private notifService: NotificationService) {
+ // opens with empty fields; accepts no data to display
}
ngOnInit() {
ranIp: new FormControl('', [Validators.required, Validators.pattern(ipPattern)]),
ranPort: new FormControl('', [Validators.required, Validators.pattern(portPattern)])
});
-
}
onCancel() {
- this.dialogRef.close();
+ this.dialogRef.close(false);
}
- public setupConnection = (ranFormValue) => {
- if (this.ranDialogForm.valid) {
- this.executeSetupConnection(ranFormValue);
+ setupConnection = (ranFormValue: RanDialogFormData) => {
+ if (!this.ranDialogForm.valid) {
+ // should never happen
+ return;
}
- }
-
- private executeSetupConnection = (ranFormValue) => {
- let httpErrRes: HttpErrorResponse;
- const aboutError = 'RAN Connection Failed: ';
+ this.processing = true;
const setupRequest: E2SetupRequest = {
ranName: ranFormValue.ranName,
ranIp: ranFormValue.ranIp,
ranPort: ranFormValue.ranPort
};
+ let observable: Observable<HttpResponse<Object>>;
if (ranFormValue.ranType === 'endc') {
- this.service.endcSetup(setupRequest).subscribe(
- (response: any) => {
- this.notifService.success('Endc connect succeeded!');
- this.dialogRef.close();
- },
- (error => {
- httpErrRes = error;
- this.errorService.displayError(aboutError + httpErrRes.message);
- })
- );
+ observable = this.service.endcSetup(setupRequest);
} else {
- this.service.x2Setup(setupRequest).subscribe(
- (response: any) => {
- this.notifService.success('X2 connect succeeded!');
- this.dialogRef.close();
- },
- (error => {
- httpErrRes = error;
- this.errorService.displayError(aboutError + httpErrRes.message);
- })
- );
+ observable = this.service.x2Setup(setupRequest);
}
+ observable.subscribe(
+ (response: any) => {
+ this.processing = false;
+ this.notifService.success('Connect succeeded!');
+ this.dialogRef.close(true);
+ },
+ ( (error: HttpErrorResponse) => {
+ this.processing = false;
+ this.errorService.displayError('RAN Connection Failed: ' + error.message);
+ // keep the dialog open
+ })
+ );
}
- public hasError(controlName: string, errorName: string) {
+ hasError(controlName: string, errorName: string) {
if (this.ranDialogForm.controls[controlName].hasError(errorName)) {
return true;
}
return false;
}
- public validateControl(controlName: string) {
+ validateControl(controlName: string) {
if (this.ranDialogForm.controls[controlName].invalid && this.ranDialogForm.controls[controlName].touched) {
return true;
}
return false;
}
-} // class AppRANConnectDialog
+}
</table>
<div class="spinner-container" *ngIf="dataSource.loading$ | async">
- <mat-spinner></mat-spinner>
+ <mat-spinner diameter=50></mat-spinner>
</div>
</div>
* ========================LICENSE_END===================================
*/
import { Component, OnInit } from '@angular/core';
+import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { MatDialog } from '@angular/material/dialog';
import { RanControlConnectDialogComponent } from './ran-connection-dialog.component';
import { E2ManagerService } from '../services/e2-mgr/e2-mgr.service';
import { ConfirmDialogService } from '../services/ui/confirm-dialog.service';
import { NotificationService } from '../services/ui/notification.service';
import { RANControlDataSource } from './ran-control.datasource';
-import { HttpErrorResponse } from '@angular/common/http';
@Component({
selector: 'rd-ran-control',
setupRANConnection() {
const dialogRef = this.dialog.open(RanControlConnectDialogComponent, {
- width: '450px',
- data: {}
+ width: '450px'
});
- dialogRef.afterClosed().subscribe(result => {
- this.dataSource.loadTable();
+ dialogRef.afterClosed().subscribe( (result: boolean) => {
+ if (result) {
+ this.dataSource.loadTable();
+ }
});
}
disconnectAllRANConnections() {
- let httpErrRes: HttpErrorResponse;
const aboutError = 'Disconnect all RAN Connections Failed: ';
this.confirmDialogService.openConfirmDialog('Are you sure you want to disconnect all RAN connections?')
- .afterClosed().subscribe(res => {
+ .afterClosed().subscribe( (res: boolean) => {
if (res) {
this.e2MgrSvc.nodebDelete().subscribe(
- response => {
+ ( response: HttpResponse<Object>) => {
if (response.status === 200) {
this.notificationService.success('Disconnect all RAN Connections Succeeded!');
this.dataSource.loadTable();
}
},
- (error => {
- httpErrRes = error;
- this.errorDialogService.displayError(aboutError + httpErrRes.message);
+ ( (error: HttpErrorResponse) => {
+ this.errorDialogService.displayError(aboutError + error.message);
})
);
}
});
}
+
}
* @param ggnbId Optional parameter for the gNB ID
* @param servingCellNrcgi Serving cell NRCGI
* @param neighborCellNrpci Neighbor cell NRPCI
- * @returns Neighbor cell relation table, which wraps an array
+ * @returns Observable of ANR neighbor cell relation array
*/
getNcrtInfo(ggnodeb: string = '', servingCellNrcgi: string = '', neighborCellNrpci: string = ''): Observable<ANRNeighborCellRelation[]> {
const url = this.buildPath(this.ncrtPath);
* @param servingCellNrcgi Serving cell NRCGI
* @param neighborCellNrpci Neighbor cell NRPCI
* @param mod Values to store in the specified relation
- * @returns Response code only, no data
+ * @returns Observable that yields a response code only, no data
*/
- modifyNcr(servingCellNrcgi: string, neighborCellNrpci: string, mod: ANRNeighborCellRelationMod): Observable<any> {
+ modifyNcr(servingCellNrcgi: string, neighborCellNrpci: string, mod: ANRNeighborCellRelationMod): Observable<Object> {
const url = this.buildPath(this.ncrtPath, this.servingPath, servingCellNrcgi, this.neighborPath, neighborCellNrpci);
return this.httpClient.put(url, mod, { observe: 'response' });
}
* Deletes neighbor cell relation based on Serving Cell NRCGI and Neighbor Cell NRPCI
* @param servingCellNrcgi Serving cell NRCGI
* @param neighborCellNrpci Neighbor cell NRPCI
- * @returns Response code only, no data
+ * @returns Observable that yields a response code only, no data
*/
- deleteNcr(servingCellNrcgi: string, neighborCellNrpci: string): Observable<any> {
+ deleteNcr(servingCellNrcgi: string, neighborCellNrpci: string): Observable<Object> {
const url = this.buildPath(this.ncrtPath, this.servingPath, servingCellNrcgi, this.neighborPath, neighborCellNrpci);
return this.httpClient.delete(url, { observe: 'response' });
}
* ========================LICENSE_END===================================
*/
import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
+import { HttpClient, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { XMXappInfo, XMDeployableApp, XMDeployedApp } from '../../interfaces/app-mgr.types';
return this.httpClient.get<XMDeployedApp[]>(this.basePath);
}
- deployXapp(name: string) {
+ deployXapp(name: string): Observable<HttpResponse<Object>> {
const xappInfo: XMXappInfo = { name: name };
return this.httpClient.post(this.basePath, xappInfo, { observe: 'response' });
}
- undeployXapp(name: string) {
+ undeployXapp(name: string): Observable<HttpResponse<Object>> {
return this.httpClient.delete((this.basePath + '/' + name), { observe: 'response' });
}
constructor(private dialog: MatDialog) { }
- openConfirmDialog(msg) {
+ openConfirmDialog(msg: string) {
return this.dialog.open(ConfirmDialogComponent, {
width: '480px',
position: { top: '100px' },
limitations under the License.
========================LICENSE_END===================================
-->
- <div class="user__section">
- <h3 class="user__header">Users</h3>
- <button mat-raised-button (click)="addUser()">Add User</button>
- <div class="spinner-container" *ngIf="dataSource.loading$ | async">
- <mat-spinner></mat-spinner>
- </div>
- <table mat-table [dataSource]="dataSource" matSort class="user-table mat-elevation-z8">
+<div class="user__section">
+ <h3 class="user__header">Users</h3>
+ <button mat-raised-button (click)="addUser()">Add User</button>
+ <div class="spinner-container" *ngIf="dataSource.loading$ | async">
+ <mat-spinner></mat-spinner>
+ </div>
+ <table mat-table [dataSource]="dataSource" matSort class="user-table mat-elevation-z8">
+
+ <ng-container matColumnDef="id">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> ID </mat-header-cell>
+ <mat-cell *matCellDef="let element"> {{element.id}} </mat-cell>
+ </ng-container>
+
+ <ng-container matColumnDef="firstName">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> First Name </mat-header-cell>
+ <mat-cell *matCellDef="let element"> {{element.firstName}} </mat-cell>
+ </ng-container>
- <ng-container matColumnDef="id">
- <mat-header-cell *matHeaderCellDef mat-sort-header> ID </mat-header-cell>
- <mat-cell *matCellDef="let element"> {{element.id}} </mat-cell>
- </ng-container>
+ <ng-container matColumnDef="lastName">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Last Name </mat-header-cell>
+ <mat-cell *matCellDef="let element"> {{element.lastName}} </mat-cell>
+ </ng-container>
- <ng-container matColumnDef="firstName">
- <mat-header-cell *matHeaderCellDef mat-sort-header> First Name </mat-header-cell>
- <mat-cell *matCellDef="let element"> {{element.firstName}} </mat-cell>
- </ng-container>
+ <ng-container matColumnDef="status">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Status </mat-header-cell>
+ <mat-cell *matCellDef="let element"> {{element.status}} </mat-cell>
+ </ng-container>
- <ng-container matColumnDef="lastName">
- <mat-header-cell *matHeaderCellDef mat-sort-header> Last Name </mat-header-cell>
- <mat-cell *matCellDef="let element"> {{element.lastName}} </mat-cell>
- </ng-container>
+ <ng-container matColumnDef="action">
+ <mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
+ <mat-cell *matCellDef="let element">
+ <div class="user-button-row">
+ <button mat-icon-button (click)="editUser(element)">
+ <mat-icon matTooltip="Edit properties">edit</mat-icon>
+ </button>
+ <button mat-icon-button color="warn" (click)="deleteUser(element)">
+ <mat-icon matTooltip="Delete user">delete</mat-icon>
+ </button>
+ </div>
+ </mat-cell>
+ </ng-container>
- <ng-container matColumnDef="status">
- <mat-header-cell *matHeaderCellDef mat-sort-header> Status </mat-header-cell>
- <mat-cell *matCellDef="let element"> {{element.status}} </mat-cell>
- </ng-container>
+ <ng-container matColumnDef="noRecordsFound">
+ <mat-footer-cell *matFooterCellDef>No records found.</mat-footer-cell>
+ </ng-container>
- <ng-container matColumnDef="action">
- <mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
- <mat-cell *matCellDef="let element">
- <div class="user-button-row">
- <button mat-icon-button (click)="editUser(element)">
- <mat-icon matTooltip="Edit properties">edit</mat-icon>
- </button>
- <button mat-icon-button color="warn" (click)="deleteUser(element)">
- <mat-icon matTooltip="Delete user">delete</mat-icon>
- </button>
- </div>
- </mat-cell>
- </ng-container>
+ <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
+ <mat-footer-row *matFooterRowDef="['noRecordsFound']" [ngClass]="{'display-none': dataSource.rowCount > 0}"></mat-footer-row>
- <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
- <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
- </table>
+ </table>
+
+ <div class="spinner-container" *ngIf="dataSource.loading$ | async">
+ <mat-spinner diameter=50></mat-spinner>
</div>
+
+</div>
\ No newline at end of file
.user-button-row button {
margin-right: 5px;
}
+
+.display-none {
+ display: none;
+}