Includes edit and delete features.
Drops the xapp screen which was for pendulum control.
Bump version to 1.0.4
Change-Id: I64c5379164dd3a52f33c782d206f11d2b792b18e
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>1.0.3-SNAPSHOT</version>
+ <version>1.0.4-SNAPSHOT</version>
</parent>
<!-- This groupId will NOT allow deployment in LF -->
<groupId>org.o-ran-sc.ric.a1med.client</groupId>
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>1.0.3-SNAPSHOT</version>
+ <version>1.0.4-SNAPSHOT</version>
</parent>
<!-- This groupId will NOT allow deployment in LF -->
<groupId>org.o-ran-sc.ric.anrxapp.client</groupId>
RIC Dashboard Release Notes
===========================
+Version 1.0.4, 29 May 2019
+--------------------------
+* Add ANR xApp neighbor cell relation table
+* Drop the pendulum xApp control screen
+
Version 1.0.3, 28 May 2019
--------------------------
* Add AC xApp controller to backend
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>1.0.3-SNAPSHOT</version>
+ <version>1.0.4-SNAPSHOT</version>
</parent>
<!-- This groupId will NOT allow deployment in LF -->
<groupId>org.o-ran-sc.ric.e2mgr.client</groupId>
<artifactId>ric-dash-parent</artifactId>
<name>RIC Dashboard project</name>
<packaging>pom</packaging>
- <version>1.0.3-SNAPSHOT</version>
+ <version>1.0.4-SNAPSHOT</version>
<!-- Properties for the license-maven-plugin in child POMs -->
<properties>
<lmp.organization.name>AT&T Intellectual Property and Nokia</lmp.organization.name>
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>1.0.3-SNAPSHOT</version>
+ <version>1.0.4-SNAPSHOT</version>
</parent>
<artifactId>ric-dash-be</artifactId>
<name>RIC Dashboard Webapp backend</name>
import org.oransc.ric.anrxapp.client.api.HealthApi;
import org.oransc.ric.anrxapp.client.api.NcrtApi;
import org.oransc.ric.anrxapp.client.invoker.ApiClient;
+import org.oransc.ric.anrxapp.client.model.GgNodeBTable;
import org.oransc.ric.anrxapp.client.model.NeighborCellRelation;
import org.oransc.ric.anrxapp.client.model.NeighborCellRelationMod;
import org.oransc.ric.anrxapp.client.model.NeighborCellRelationTable;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final NeighborCellRelationTable ncrt, ncrtNodeB1, ncrtNodeB2;
+ private final GgNodeBTable gNodebTable;
public AnrXappMockConfiguration() {
logger.info("Configuring mock ANR xApp client");
+ gNodebTable = new GgNodeBTable();
+ gNodebTable.addGNodeBIdsItem("A").addGNodeBIdsItem("B");
ncrtNodeB1 = new NeighborCellRelationTable();
ncrtNodeB2 = new NeighborCellRelationTable();
ncrt = new NeighborCellRelationTable();
}
@Bean
- public HealthApi anrHealthMockApi() {
- ApiClient mockClient = mock(ApiClient.class);
- when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
+ public HealthApi anrHealthApi() {
+ ApiClient apiClient = apiClient();
HealthApi mockApi = mock(HealthApi.class);
- when(mockApi.getApiClient()).thenReturn(mockClient);
+ when(mockApi.getApiClient()).thenReturn(apiClient);
doAnswer(i -> {
return null;
}).when(mockApi).getHealthAlive();
ApiClient apiClient = apiClient();
NcrtApi mockApi = mock(NcrtApi.class);
when(mockApi.getApiClient()).thenReturn(apiClient);
+ when(mockApi.getgNodeB()).thenReturn(gNodebTable);
// 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);
@ApiOperation(value = "Gets the A1 client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@RequestMapping(value = DashboardConstants.VERSION_PATH, method = RequestMethod.GET)
- public SuccessTransport getVersion() {
- logger.debug("getVersion enter");
+ public SuccessTransport getA1MediatorClientVersion() {
return new SuccessTransport(200, DashboardApplication.getImplementationVersion(A1MediatorApi.class));
}
@ApiOperation(value = "Gets the ANR client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@RequestMapping(value = DashboardConstants.VERSION_PATH, method = RequestMethod.GET)
- public SuccessTransport getVersion() {
- logger.debug("getVersion enter");
+ public SuccessTransport getAnrXappClientVersion() {
return new SuccessTransport(200, DashboardApplication.getImplementationVersion(HealthApi.class));
}
@ApiOperation(value = "Performs a liveness probe on the ANR xApp, result expressed as the response code.")
@RequestMapping(value = "/health/alive", method = RequestMethod.GET)
- public void getHealthAlive(HttpServletResponse response) {
- logger.debug("getHealthAlive");
+ public void getAnrXappHealthAlive(HttpServletResponse response) {
healthApi.getHealthAlive();
response.setStatus(healthApi.getApiClient().getStatusCode().value());
}
@ApiOperation(value = "Performs a readiness probe on the ANR xApp, result expressed as the response code.")
@RequestMapping(value = "/health/ready", method = RequestMethod.GET)
- public void getHealthReady(HttpServletResponse response) {
- logger.debug("getHealthReady");
+ public void getAnrXappHealthReady(HttpServletResponse response) {
healthApi.getHealthReady();
response.setStatus(healthApi.getApiClient().getStatusCode().value());
}
@RequestParam(name = QP_NODEB, required = false) String ggnbId, //
@RequestParam(name = QP_SERVING, required = false) String servingCellNrcgi, //
@RequestParam(name = QP_NEIGHBOR, required = false) String neighborCellNrpci) {
- logger.debug("getNcrtInfo: ggnbid {}, servingCellNrpci {} neighborCellNrcgi {}", ggnbId, servingCellNrcgi,
+ logger.debug("getNcrtInfo: ggnbid {}, servingCellNrpci {}, neighborCellNrcgi {}", ggnbId, servingCellNrcgi,
neighborCellNrpci);
return ncrtApi.getNcrt(ggnbId, servingCellNrcgi, neighborCellNrpci);
}
@ApiOperation(value = "Gets the E2 manager client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@RequestMapping(value = DashboardConstants.VERSION_PATH, method = RequestMethod.GET)
- public SuccessTransport getVersion() {
- logger.debug("getVersion enter");
+ public SuccessTransport getE2ManagerClientVersion() {
return new SuccessTransport(200, DashboardApplication.getImplementationVersion(HealthCheckApi.class));
}
@ApiOperation(value = "Gets the health from the E2 manager, expressed as the response code.")
@RequestMapping(value = "/health", method = RequestMethod.GET)
- public void getHealth(HttpServletResponse response) {
- logger.debug("getHealth");
+ public void getE2ManagerHealth(HttpServletResponse response) {
e2HealthCheckApi.healthGet();
response.setStatus(e2HealthCheckApi.getApiClient().getStatusCode().value());
}
import org.oransc.ric.portal.dashboard.DashboardApplication;
import org.oransc.ric.portal.dashboard.DashboardConstants;
import org.oransc.ric.portal.dashboard.model.SuccessTransport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@RequestMapping(value = DashboardConstants.ENDPOINT_PREFIX + "/dashboard", produces = MediaType.APPLICATION_JSON_VALUE)
public class HealthcheckController {
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
@ApiOperation(value = "Checks the health of the application by (TBD).", response = SuccessTransport.class)
@RequestMapping(value = DashboardConstants.HEALTHCHECK_PATH, method = RequestMethod.GET)
- public SuccessTransport getHealth() {
- logger.debug("getHealth enter");
+ public SuccessTransport getDashblardHealth() {
long count = 0;
return new SuccessTransport(200, "(TBD) reports count is " + count);
}
@ApiOperation(value = "Gets the Dashboard MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@RequestMapping(value = DashboardConstants.VERSION_PATH, method = RequestMethod.GET)
- public SuccessTransport getVersion() {
- logger.debug("getVersion enter");
+ public SuccessTransport getDashboardVersion() {
return new SuccessTransport(200,
DashboardApplication.getImplementationVersion(MethodHandles.lookup().lookupClass()));
}
@ApiOperation(value = "Gets the XApp manager client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@RequestMapping(value = DashboardConstants.VERSION_PATH, method = RequestMethod.GET)
- public SuccessTransport getVersion() {
- logger.debug("getVersion enter");
+ public SuccessTransport getXappManagerClientVersion() {
return new SuccessTransport(200, DashboardApplication.getImplementationVersion(HealthApi.class));
}
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>1.0.3-SNAPSHOT</version>
+ <version>1.0.4-SNAPSHOT</version>
</parent>
<artifactId>ric-dash-fe</artifactId>
<name>RIC Dashboard Webapp frontend</name>
--- /dev/null
+<!--
+ ========================LICENSE_START=================================
+ O-RAN-SC
+ %%
+ Copyright (C) 2019 AT&T Intellectual Property and Nokia
+ %%
+ 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.
+ ========================LICENSE_END===================================
+ -->
+
+<div mat-dialog-title>
+ Edit Neighbor Cell Relation
+</div>
+
+<form [formGroup]="ncrDialogForm" novalidate autocomplete="off" (ngSubmit)="modifyNcr(ncrDialogForm.value)">
+ <div mat-dialog-content>
+ <mat-form-field class="input-display-block">
+ <input matInput readonly type="text" placeholder="Serving cell NRCGI" formControlName="servingCellNrcgi">
+ </mat-form-field>
+ <mat-form-field class="input-display-block">
+ <input matInput readonly type="text" placeholder="Neighbor cell NRPCI" formControlName="neighborCellNrpci">
+ </mat-form-field>
+ <mat-form-field class="input-display-block">
+ <input matInput type="text" placeholder="Neighbor cell NRCGI" formControlName="neighborCellNrcgi">
+ <mat-hint align="end">Example: A12345</mat-hint>
+ <mat-error *ngIf="validateControl('neighborCellNrcgi') && hasError('neighborCellNrcgi', 'required')">Neighbor cell identifier is required</mat-error>
+ <mat-error *ngIf="hasError('neighborCellNrcgi', 'pattern')">Valid NRCGI is required</mat-error>
+ </mat-form-field>
+ <div name="flagNoHo">
+ <mat-checkbox formControlName="flagNoHo">Flag No Handover</mat-checkbox>
+ </div>
+ <div name="flagNoXn">
+ <mat-checkbox formControlName="flagNoXn">Flag No Transaction</mat-checkbox>
+ </div>
+ <div name="flagNoRemove">
+ <mat-checkbox formControlName="flagNoRemove">Flag No Remove</mat-checkbox>
+ </div>
+</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]="!ncrDialogForm.valid">Save</button>
+ </div>
+</form>
* 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.
* limitations under the License.
* ========================LICENSE_END===================================
*/
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { XappComponent } from './xapp.component';
-
-describe('XappComponent', () => {
- let component: XappComponent;
- let fixture: ComponentFixture<XappComponent>;
-
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- declarations: [ XappComponent ]
- })
- .compileComponents();
- }));
-
- beforeEach(() => {
- fixture = TestBed.createComponent(XappComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
+ /* used to place form fields on separate lines/rows in dialog */
+.input-display-block {
+ display: block;
+ }
\ No newline at end of file
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 AT&T Intellectual Property and Nokia
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+import { Component, OnInit, Inject } from '@angular/core';
+import { FormGroup, FormControl, Validators } from '@angular/forms';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { ANRXappService } from '../services/anr-xapp/anr-xapp.service';
+import { ErrorDialogService } from '../services/ui/error-dialog.service';
+import { ANRNeighborCellRelation, ANRNeighborCellRelationMod } from '../interfaces/anr-xapp.types';
+import { modelGroupProvider } from '@angular/forms/src/directives/ng_model_group';
+
+@Component({
+ selector: 'app-ncr-edit-dialog',
+ templateUrl: './anr-edit-ncr-dialog.component.html',
+ styleUrls: ['./anr-edit-ncr-dialog.component.scss']
+})
+
+export class ANREditNCRDialogComponent implements OnInit {
+
+ private ncrDialogForm: FormGroup;
+
+ constructor(
+ private dialogRef: MatDialogRef<ANREditNCRDialogComponent>,
+ private dataService: ANRXappService, private errorService: ErrorDialogService,
+ @Inject(MAT_DIALOG_DATA) private data: ANRNeighborCellRelation) {
+ console.log('constructed with data ' + data);
+ }
+
+ ngOnInit() {
+ const namePattern = /^([A-Z])+([0-9])+$/;
+ this.ncrDialogForm = new FormGroup({
+ servingCellNrcgi: new FormControl(this.data.servingCellNrcgi), // readonly
+ neighborCellNrpci: new FormControl(this.data.neighborCellNrpci), // readonly
+ neighborCellNrcgi: new FormControl(this.data.neighborCellNrcgi, [Validators.required, Validators.pattern(namePattern)]),
+ flagNoHo: new FormControl(this.data.flagNoHo),
+ flagNoXn: new FormControl(this.data.flagNoXn),
+ flagNoRemove: new FormControl(this.data.flagNoRemove)
+ });
+ }
+
+ onCancel() {
+ this.dialogRef.close();
+ }
+
+ modifyNcr = (ncrFormValue: ANRNeighborCellRelation) => {
+ if (this.ncrDialogForm.valid) {
+ const ncrm = {} as ANRNeighborCellRelationMod;
+ // there must be a btter way
+ ncrm.neighborCellNrcgi = ncrFormValue.neighborCellNrcgi;
+ ncrm.neighborCellNrpci = ncrFormValue.neighborCellNrpci;
+ ncrm.flagNoHo = ncrFormValue.flagNoHo;
+ ncrm.flagNoXn = ncrFormValue.flagNoXn;
+ ncrm.flagNoRemove = ncrFormValue.flagNoRemove;
+ this.dataService.modifyNcr(ncrFormValue.servingCellNrcgi, ncrFormValue.neighborCellNrpci, ncrm).subscribe((val: any[]) => {},
+ (error => {
+ this.errorService.displayError('NCR update failed: ' + error.message);
+ })
+ );
+ this.dialogRef.close();
+ }
+ }
+
+ public hasError(controlName: string, errorName: string) {
+ if (this.ncrDialogForm.controls[controlName].hasError(errorName)) {
+ return true;
+ }
+ return false;
+ }
+
+ public validateControl(controlName: string) {
+ if (this.ncrDialogForm.controls[controlName].invalid && this.ncrDialogForm.controls[controlName].touched) {
+ return true;
+ }
+ return false;
+ }
+
+}
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.
========================LICENSE_END===================================
-->
<div class="anr__section">
- <h3 class="anr__header">ANR xApp</h3>
- <ng2-smart-table [settings]="settings" [source]="source" (custom)="onAnrControlAction($event)">
- </ng2-smart-table>
- <app-modal-event hidden></app-modal-event>
-</div>
+ <h3 class="anr__header">ANR xApp Neighbor Cell Relation Table</h3>
+
+ <mat-form-field>
+ <mat-label>GgNodeB</mat-label>
+ <!-- use a native selection widget -->
+ <select matNativeControl #ggNodeB (selectionChange)="loadNcrtPage()">
+ <option value="" selected>Select..</option>
+ <option *ngFor="let g of gNodeBIds" [value]="g">{{g}}</option>
+ </select>
+ </mat-form-field>
+ <mat-form-field class="input-pad-left">
+ <input matInput placeholder="Serving Cell NRCGI" #servingCellNrcgi>
+ </mat-form-field>
+ <mat-form-field class="input-pad-left">
+ <input matInput placeholder="Neighbor cell NRPCI" #neighborCellNrpci>
+ </mat-form-field>
+
+ <div class="spinner-container" *ngIf="dataSource.loading$ | async">
+ <mat-spinner></mat-spinner>
+ </div>
+
+ <table mat-table class="ncr-table mat-elevation-z8" [dataSource]="dataSource">
+
+ <ng-container matColumnDef="cellIdentifierNrcgi">
+ <mat-header-cell *matHeaderCellDef>Serving Cell NRCGI</mat-header-cell>
+ <mat-cell *matCellDef="let ncr">{{ncr.servingCellNrcgi}}</mat-cell>
+ </ng-container>
+
+ <ng-container matColumnDef="neighborCellNrpci">
+ <mat-header-cell *matHeaderCellDef>Neighbor Cell NRPCI</mat-header-cell>
+ <mat-cell *matCellDef="let ncr">{{ncr.neighborCellNrpci}}</mat-cell>
+ </ng-container>
+
+ <ng-container matColumnDef="neighborCellNrcgi">
+ <mat-header-cell *matHeaderCellDef>Neighbor Cell NRCGI</mat-header-cell>
+ <mat-cell *matCellDef="let ncr">{{ncr.neighborCellNrcgi}}</mat-cell>
+ </ng-container>
+
+ <ng-container matColumnDef="flagNoHo">
+ <mat-header-cell *matHeaderCellDef>Flag No Handover</mat-header-cell>
+ <mat-cell *matCellDef="let ncr">{{ncr.flagNoHo}}</mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="flagNoXn">
+ <mat-header-cell *matHeaderCellDef>Flag No Xn</mat-header-cell>
+ <mat-cell *matCellDef="let ncr">{{ncr.flagNoXn}}</mat-cell>
+ </ng-container>
+
+ <ng-container matColumnDef="flagNoRemove">
+ <mat-header-cell *matHeaderCellDef>Flag No Remove</mat-header-cell>
+ <mat-cell *matCellDef="let ncr">{{ncr.flagNoRemove}}</mat-cell>
+ </ng-container>
+
+ <ng-container matColumnDef="action">
+ <mat-header-cell *matHeaderCellDef>Action</mat-header-cell>
+ <mat-cell class="action-cell" *matCellDef="let ncr">
+ <button mat-icon-button (click)="modifyNcr(ncr)">
+ <mat-icon>edit</mat-icon>
+ </button>
+ <button mat-icon-button color="warn" (click)="deleteNcr(ncr)">
+ <mat-icon>delete</mat-icon>
+ </button>
+ </mat-cell>
+ </ng-container>
+
+ <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
+
+ <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
+
+ </table>
+
+ <div class="version__text">
+ ANR client version {{anrClientVersion}}
+ </div>
+</div>
* 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.
*/
.anr__section {
position: relative;
- top: -150px;
+ top: -50px;
}
.anr__header {
transform: translate(149 56);
}
-:host /deep/ ng2-smart-table tbody > tr > td{
- text-align: left;
+.spinner-container {
+ height: 360px;
+ width: 390px;
+ position: fixed;
}
-:host /deep/ ng2-smart-table thead th{
- text-align: left;
+.spinner-container mat-spinner {
+ margin: 130px auto 0 auto;
+}
+
+.ncr-table {
+ width: 99%; /* 100 looks wrong */
+ min-height: 150px;
+ margin-top: 10px;
+ background-color:transparent;
+}
+
+.ncr-table__bg-dark {
+ color: white;
+}
+
+.input-pad-left {
+ padding-left: 10px;
+}
+
+.input-pad-right {
+ padding-right: 10px;
+}
+
+.version__text {
+ color: gray;
+ letter-spacing: 0.1rem;
+ font-size: 10px;
}
* 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.
* 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.
* limitations under the License.
* ========================LICENSE_END===================================
*/
-import { Component, OnInit } from '@angular/core';
+
+import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { fromEvent } from 'rxjs/observable/fromEvent';
+import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
+import { ANRNeighborCellRelation } from '../interfaces/anr-xapp.types';
+import { ANRXappDataSource } from './anr-xapp.datasource';
+import { ANRXappService } from '../services/anr-xapp/anr-xapp.service';
+import { ANREditNCRDialogComponent } from './anr-edit-ncr-dialog.component';
+import { ConfirmDialogService } from './../services/ui/confirm-dialog.service';
+import { ErrorDialogService } from '../services/ui/error-dialog.service';
+import { NotificationService } from './../services/ui/notification.service';
@Component({
- selector: 'app-anr-xapp',
+ selector: 'app-anr',
templateUrl: './anr-xapp.component.html',
styleUrls: ['./anr-xapp.component.scss']
})
-export class AnrXappComponent implements OnInit {
+export class AnrXappComponent implements AfterViewInit, OnInit {
+
+ dataSource: ANRXappDataSource;
+ anrClientVersion: string;
+ gNodeBIds: string[];
+ @ViewChild('ggNodeB') ggNodeB: ElementRef;
+ @ViewChild('servingCellNrcgi') servingCellNrcgi: ElementRef;
+ @ViewChild('neighborCellNrpci') neighborCellNrpci: ElementRef;
+
+ displayedColumns = ['cellIdentifierNrcgi', 'neighborCellNrpci', 'neighborCellNrcgi',
+ 'flagNoHo', 'flagNoXn', 'flagNoRemove', 'action'];
- constructor() { }
+ constructor(
+ private anrXappService: ANRXappService,
+ private dialog: MatDialog,
+ private confirmDialogService: ConfirmDialogService,
+ private errorDialogService: ErrorDialogService,
+ private notificationService: NotificationService) { }
ngOnInit() {
+ this.dataSource = new ANRXappDataSource(this.anrXappService);
+ this.dataSource.loadTable();
+ // Empty string occurs first in the array of gNodeBIds
+ this.anrXappService.getgNodeBs().subscribe((res: string[]) => this.gNodeBIds = res);
+ this.anrXappService.getVersion().subscribe((res: string) => this.anrClientVersion = res);
+ }
+
+ ngAfterViewInit() {
+ // the selector event calls loadNcrtPage() directly.
+ fromEvent(this.servingCellNrcgi.nativeElement, 'keyup')
+ .pipe(
+ debounceTime(150),
+ distinctUntilChanged(),
+ tap(() => {
+ this.loadNcrtPage();
+ })
+ )
+ .subscribe();
+ fromEvent(this.neighborCellNrpci.nativeElement, 'keyup')
+ .pipe(
+ debounceTime(150),
+ distinctUntilChanged(),
+ tap(() => {
+ this.loadNcrtPage();
+ })
+ )
+ .subscribe();
+ }
+
+ loadNcrtPage() {
+ this.dataSource.loadTable(
+ this.ggNodeB.nativeElement.value,
+ this.servingCellNrcgi.nativeElement.value,
+ this.neighborCellNrpci.nativeElement.value);
+ }
+
+ modifyNcr(ncr: ANRNeighborCellRelation): void {
+ const dialogRef = this.dialog.open(ANREditNCRDialogComponent, {
+ width: '300px',
+ data: ncr
+ });
+ dialogRef.afterClosed().subscribe(result => {
+ this.loadNcrtPage();
+ });
+ }
+
+ deleteNcr(ncr: ANRNeighborCellRelation): void {
+ this.confirmDialogService
+ .openConfirmDialog('Are you sure you want to delete this relation?')
+ .afterClosed().subscribe(res => {
+ if (res) {
+ this.anrXappService.deleteNcr(ncr.servingCellNrcgi, ncr.neighborCellNrpci)
+ .subscribe(
+ response => {
+ switch (response.status) {
+ case 200:
+ this.notificationService.success('Delete succeeded!');
+ break;
+ default:
+ this.notificationService.warn('Delete failed.');
+ }
+ },
+ error => {
+ this.errorDialogService.displayError(error.message);
+ });
+ }
+ });
}
}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 AT&T Intellectual Property and Nokia
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+import { CollectionViewer, DataSource} from '@angular/cdk/collections';
+import { Observable } from 'rxjs/Observable';
+import { catchError, finalize } from 'rxjs/operators';
+import { of } from 'rxjs/observable/of';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+import { ANRNeighborCellRelation } from '../interfaces/anr-xapp.types';
+import { ANRXappService } from '../services/anr-xapp/anr-xapp.service';
+
+// https://blog.angular-university.io/angular-material-data-table/
+export class ANRXappDataSource extends DataSource<ANRNeighborCellRelation> {
+
+ private relationsSubject = new BehaviorSubject<ANRNeighborCellRelation[]>([]);
+
+ private loadingSubject = new BehaviorSubject<boolean>(false);
+
+ public loading$ = this.loadingSubject.asObservable();
+
+ constructor(private anrXappService: ANRXappService) {
+ super();
+ }
+
+ loadTable(ggnodeb = '', servingCellNrcgi = '', neighborCellNrpci = '') {
+ this.loadingSubject.next(true);
+ this.anrXappService.getNcrtInfo(ggnodeb, servingCellNrcgi, neighborCellNrpci)
+ .pipe(
+ catchError(() => of([])),
+ finalize(() => this.loadingSubject.next(false))
+ )
+ .subscribe(ncrt => this.relationsSubject.next(ncrt));
+ }
+
+ connect(collectionViewer: CollectionViewer): Observable<ANRNeighborCellRelation[]> {
+ return this.relationsSubject.asObservable();
+ }
+
+ disconnect(collectionViewer: CollectionViewer): void {
+ this.relationsSubject.complete();
+ this.loadingSubject.complete();
+ }
+
+}
import { RANConnectionComponent } from './ran-connection/ran-connection.component';
import { StatsComponent } from './stats/stats.component';
import { AdminComponent } from './admin/admin.component';
-import { XappComponent } from './xapp/xapp.component';
+import { AnrXappComponent } from './anr-xapp/anr-xapp.component';
const routes: Routes = [
{path: '', component: LoginComponent},
{path: 'ran-connection', component: RANConnectionComponent},
{path: 'stats', component: StatsComponent},
{path: 'admin', component: AdminComponent},
- {path: 'xapp', component: XappComponent},
+ {path: 'anr', component: AnrXappComponent},
];
@NgModule({
*/
import { BrowserModule } from '@angular/platform-browser';
// tslint:disable-next-line:max-line-length
-import {MatButtonModule, MatButtonToggleModule, MatCardModule, MatDialogModule,
- MatExpansionModule, MatFormFieldModule, MatGridListModule, MatIconModule,
- MatInputModule, MatListModule, MatPaginatorModule, MatProgressSpinnerModule,
- MatSidenavModule, MatSliderModule, MatSlideToggleModule, MatSnackBarModule,
- MatSortModule,MatTableModule, MatTabsModule} from '@angular/material';
+import {MatButtonModule, MatButtonToggleModule, MatCardModule, MatCheckboxModule,
+ MatDialogModule, MatExpansionModule, MatFormFieldModule, MatGridListModule,
+ MatIconModule, MatInputModule, MatListModule, MatPaginatorModule,
+ MatProgressSpinnerModule, MatSelectModule, MatSidenavModule, MatSliderModule,
+ MatSlideToggleModule, MatSnackBarModule, MatSortModule, MatTableModule,
+ MatTabsModule} from '@angular/material';
import { BrowserAnimationsModule} from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
-import { Ng2SmartTableModule } from 'ng2-smart-table';
import { MatRadioModule } from '@angular/material/radio';
import { ChartsModule } from 'ng2-charts';
import { MDBBootstrapModule } from 'angular-bootstrap-md';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+// RETIRE THIS
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { ControlComponent } from './control/control.component';
import { RANConnectionDialogComponent } from './ran-connection/ran-connection-dialog.component';
import { RANConnectionComponent } from './ran-connection/ran-connection.component';
+import { ANREditNCRDialogComponent } from './anr-xapp/anr-edit-ncr-dialog.component';
import { StatsComponent } from './stats/stats.component';
import { AdminComponent } from './admin/admin.component';
import { CatalogCardComponent } from './ui/catalog-card/catalog-card.component';
import { ControlCardComponent } from './ui/control-card/control-card.component';
import { StatCardComponent } from './ui/stat-card/stat-card.component';
import { ModalEventComponent } from './ui/modal-event/modal-event.component';
-import { XappComponent } from './xapp/xapp.component';
import { ConfigEventComponent } from './ui/config-event/config-event.component';
import { ConfirmDialogComponent } from './ui/confirm-dialog/confirm-dialog.component';
import { FooterComponent } from './footer/footer.component';
StatsComponent,
AdminComponent,
ModalEventComponent,
- XappComponent,
ConfigEventComponent,
AnrXappComponent,
RANConnectionDialogComponent,
+ ANREditNCRDialogComponent,
ConfirmDialogComponent,
FooterComponent,
ErrorDialogComponent
],
imports: [
+ AppRoutingModule,
BrowserModule,
BrowserAnimationsModule,
ChartsModule,
- AppRoutingModule,
FormsModule,
- MatDialogModule,
- ReactiveFormsModule,
+ MatButtonModule,
MatButtonToggleModule,
- MatExpansionModule,
- MatRadioModule,
- MatSliderModule,
MatCardModule,
- MatIconModule,
+ MatCheckboxModule,
+ MatDialogModule,
+ MatExpansionModule,
+ MatFormFieldModule,
MatGridListModule,
+ MatIconModule,
+ MatInputModule,
MatListModule,
+ MatPaginatorModule,
+ MatProgressSpinnerModule,
+ MatRadioModule,
+ MatSelectModule,
+ MatSliderModule,
MatSidenavModule,
MatSlideToggleModule,
+ MatSnackBarModule,
+ MatSortModule,
MatTableModule,
MatTabsModule,
- MatSortModule,
- MatFormFieldModule,
- MatButtonModule,
- MatInputModule,
- MatProgressSpinnerModule,
Ng2SmartTableModule,
- MatSnackBarModule,
+ ReactiveFormsModule,
MDBBootstrapModule.forRoot(),
],
exports: [
],
entryComponents: [
RANConnectionDialogComponent,
+ ANREditNCRDialogComponent,
ConfirmDialogComponent,
ErrorDialogComponent
],
<ng-container matColumnDef="action">
<mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
- <mat-cell *matCellDef="let element">
- <button mat-icon-button
- (click)="view()">
+ <!-- click on button should not expand/collapse the row -->
+ <mat-cell *matCellDef="let element" (click)="$event.stopPropagation()">
+ <button mat-icon-button (click)="controlApp(element)">
<mat-icon>settings</mat-icon>
</button>
- <button mat-icon-button
- color="warn"
- (click)="undeploy(element.xapp)">
+ <button mat-icon-button color="warn" (click)="undeployApp(element)">
<mat-icon>delete</mat-icon>
</button>
</mat-cell>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let element; columns: displayedColumns;"
- [class.example-expanded-row]="expandedElement === element"
- (click)="expandedElement = expandedElement === element ? null : element"></mat-row>
+ [class.example-expanded-row]="expandedElement === element"
+ (click)="expandedElement = expandedElement === element ? null : element"></mat-row>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="message-row"></tr>
</table>
-</div>
+</div>
\ No newline at end of file
* 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.
import { Component, OnInit } from '@angular/core';
import { XappMgrService } from '../services/xapp-mgr/xapp-mgr.service';
import { Router } from '@angular/router';
-import { ConfirmDialogService } from './../services/ui/confirm-dialog.service'
-import { NotificationService } from './../services/ui/notification.service'
-import { XMXapp } from '../interfaces/xapp-mgr.types';
+import { ErrorDialogService } from './../services/ui/error-dialog.service';
+import { ConfirmDialogService } from './../services/ui/confirm-dialog.service';
+import { NotificationService } from './../services/ui/notification.service';
+import { XappControlRow } from '../interfaces/xapp-mgr.types';
import { ControlAnimations } from './control.animations';
import { ControlDataSource } from './control.datasource';
-
+import { routerNgProbeToken } from '@angular/router/src/router_module';
@Component({
selector: 'app-control',
private xappMgrSvc: XappMgrService,
private router: Router,
private confirmDialogService: ConfirmDialogService,
+ private errorDialogService: ErrorDialogService,
private notification: NotificationService) { }
ngOnInit() {
this.dataSource.loadTable();
}
- view(): void {
- const url = '/xapp';
- this.router.navigate([url]);
+ controlApp(app: XappControlRow): void {
+ const anrXappPattern = /[Aa][Nn][Rr]/;
+ if (anrXappPattern.test(app.xapp)) {
+ this.router.navigate(['/anr']);
+ } else {
+ this.errorDialogService.displayError('No control available for ' + app.xapp + ' (yet)');
+ }
}
- undeploy(name: string): void {
- this.confirmDialogService.openConfirmDialog('Are you sure you want to undeploy this xApp ?')
+ undeployApp(app: XappControlRow): void {
+ this.confirmDialogService.openConfirmDialog('Are you sure you want to undeploy xApp ' + app.xapp + '?')
.afterClosed().subscribe(res => {
if (res) {
- this.xappMgrSvc.undeployXapp(name).subscribe(
+ this.xappMgrSvc.undeployXapp(app.xapp).subscribe(
response => {
this.dataSource.loadTable();
switch (response.status) {
});
}
-
-
}
// Models of data used by the ANR xApp
+export interface ANRGgNodeBTable {
+ gNodeBIds: Array<string>;
+}
+
+export interface ANRNeighborCellRelationTable {
+ ncrtRelations: Array<ANRNeighborCellRelation>;
+}
+
export interface ANRNeighborCellRelation {
- cellIdentifierNrcgi: string;
+ servingCellNrcgi: string;
neighborCellNrpci: string;
neighborCellNrcgi: string;
flagNoHo: boolean;
flagNoRemove: boolean;
}
-export interface ANRNeighborCellRelationDel {
- idType: string;
- neighborCellNrpci: string;
- neighborCellNrcgi: string;
-}
-
export interface ANRNeighborCellRelationMod {
- neighbourCellIdentifierType: string;
- action: string;
+ servingCellNrcgi: string;
neighborCellNrpci: string;
neighborCellNrcgi: string;
flagNoHo: boolean;
export interface XappControlRow {
xapp: string;
instance: XMXappInstance;
-}
\ No newline at end of file
+}
limitations under the License.
========================LICENSE_END===================================
-->
+
+<!-- browse icons at https://material.io/tools/icons/?style=baseline -->
<mat-nav-list>
<a mat-list-item routerLink="/login" (click)="onSidenavClose()">
<mat-icon>home</mat-icon> <span class="nav-caption">Home</span>
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
import { DashboardSuccessTransport } from '../../interfaces/dashboard.types';
import { ANRNeighborCellRelation, ANRNeighborCellRelationMod } from '../../interfaces/anr-xapp.types';
@Injectable({
providedIn: 'root'
})
-export class AnrXappService {
+export class ANRXappService {
- private basePath = 'api/xapp/anr/';
- private cellPath = 'cell/cellIdentifier/';
+ // Trailing slashes are confusing so omit them here
+ private basePath = 'api/xapp/anr';
+ private ncrtPath = 'ncrt';
+ private servingPath = 'servingcells';
+ private neighborPath = 'neighborcells';
constructor(private httpClient: HttpClient) {
// injects to variable httpClient
}
+ private buildPath(...args: any[]) {
+ let result = this.basePath;
+ args.forEach(part => {
+ result = result + '/' + part;
+ });
+ return result;
+ }
+
/**
* Gets ANR xApp client version details
* @returns Observable that should yield a DashboardSuccessTransport
*/
- getVersion(): Observable<DashboardSuccessTransport> {
- return this.httpClient.get<DashboardSuccessTransport>(this.basePath + 'version');
+ getVersion(): Observable<string> {
+ const url = this.buildPath('version');
+ return this.httpClient.get<DashboardSuccessTransport>(url).pipe(
+ // Extract the string here
+ map(res => res['data'])
+ );
}
/**
* @returns Observable that should yield a response code (no data)
*/
getHealthAlive(): Observable<any> {
- return this.httpClient.get(this.basePath + 'health/alive');
+ const url = this.buildPath('health/alive');
+ return this.httpClient.get(url);
}
/**
* @returns Observable that should yield a response code (no data)
*/
getHealthReady(): Observable<any> {
- return this.httpClient.get(this.basePath + 'health/ready');
+ const url = this.buildPath('health/ready');
+ return this.httpClient.get(url);
+ }
+
+ /**
+ * Gets ANR xApp client version details
+ * @returns Observable that should yield a DashboardSuccessTransport
+ */
+ getgNodeBs(): Observable<string[]> {
+ const url = this.buildPath('gnodebs');
+ return this.httpClient.get<string[]>(url).pipe(
+ // Extract the array of IDs here
+ map(res => res['gNodeBIds'])
+ );
}
/**
- * Query NCRT of all cells, all or one gNB(s)
+ * Gets the neighbor cell relation table for all gNodeBs or based on query parameters
* @param ggnbId Optional parameter for the gNB ID
- * @param startIndex Optional parameter for the start index
- * @param limit Optional parameter for the limit (page size)
- * @returns Observable of ANRNeighborCellRelation
+ * @param servingCellNrcgi Serving cell NRCGI
+ * @param neighborCellNrpci Neighbor cell NRPCI
+ * @returns Neighbor cell relation table, which wraps an array
*/
- getNcrtInfo(ggnbId?: string, startIndex?: string, limit?: number): Observable<ANRNeighborCellRelation[]> {
- const queryParams = new HttpParams();
- if (ggnbId) {
- queryParams.set('ggnbid', ggnbId);
- }
- if (startIndex) {
- queryParams.set('startIndex', startIndex);
- }
- if (limit) {
- queryParams.set('limit', limit.toString());
- }
- return this.httpClient.get<ANRNeighborCellRelation[]>(this.basePath + 'cell', { params: queryParams } );
+ getNcrtInfo(ggnodeb: string = '', servingCellNrcgi: string = '', neighborCellNrpci: string = ''): Observable<ANRNeighborCellRelation[]> {
+ const url = this.buildPath(this.ncrtPath);
+ return this.httpClient.get<ANRNeighborCellRelation[]>(url, {
+ params: new HttpParams()
+ .set('ggnodeb', ggnodeb)
+ .set('servingCellNrcgi', servingCellNrcgi)
+ .set('neighborCellNrpci', neighborCellNrpci)
+ }).pipe(
+ // Extract the array of relations here
+ map(res => res['ncrtRelations'])
+ );
}
/**
- * Query NCRT of a single serving cell, all or one gNB(s)
- * @param cellId cell ID
- * @param ggnbid Optional parameter for the gNB ID
- * @param startIndex Optional parameter for the start index
- * @param limit Optional parameter for the limit (page size)
- * @returns Observable of ANRNeighborCellRelation
+ * Modify neighbor cell relation based on Serving Cell NRCGI and Neighbor Cell NRPCI
+ * @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
*/
- getCellNcrtInfo(cellId: string, ggnbId?: string, startIndex?: string, limit?: number): Observable<ANRNeighborCellRelation[]> {
- const queryParams = new HttpParams();
- if (ggnbId) {
- queryParams.set('ggnbid', ggnbId);
- }
- if (startIndex) {
- queryParams.set('startIndex', startIndex);
- }
- if (limit) {
- queryParams.set('limit', limit.toString());
- }
- return this.httpClient.get<ANRNeighborCellRelation[]>(this.basePath + this.cellPath + cellId, { params: queryParams } );
+ modifyNcr(servingCellNrcgi: string, neighborCellNrpci: string, mod: ANRNeighborCellRelationMod): Observable<any> {
+ const url = this.buildPath(this.ncrtPath, this.servingPath, servingCellNrcgi, this.neighborPath, neighborCellNrpci);
+ return this.httpClient.put(url, mod, { observe: 'response' });
}
/**
- * Modify neighbor cell relations based on Source Cell NR CGI and Target Cell NR PCI / NR CGI
- * @param cellId cell ID
- * @param table Array of ANRNeighborCellRelationMod
- * @returns Observable that should yield a response code (no data)
+ * 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
*/
- modifyNcrt(cellId: string, table: ANRNeighborCellRelationMod []): Observable<any> {
- return this.httpClient.put(this.basePath + this.cellPath + cellId, table);
+ deleteNcr(servingCellNrcgi: string, neighborCellNrpci: string): Observable<any> {
+ const url = this.buildPath(this.ncrtPath, this.servingPath, servingCellNrcgi, this.neighborPath, neighborCellNrpci);
+ return this.httpClient.delete(url, { observe: 'response' });
}
- /** TODO: deleteNcrt */
-
}
getAll(): Observable<XMXapp[]>{
return this.httpClient.get<XMXapp[]>(this.basePath)
-
}
deployXapp(name: string) {
return this.httpClient.delete((this.basePath + '/' + name), { observe: 'response' });
}
-}
\ No newline at end of file
+}
+++ /dev/null
-<!--
- ========================LICENSE_START=================================
- O-RAN-SC
- %%
- Copyright (C) 2019 AT&T Intellectual Property and Nokia
- %%
- 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.
- ========================LICENSE_END===================================
- -->
-
-<div>
- <p class="heading lead">Pendulum Control xApp</p>
- <p>Pod ID: dc-ric-app-b8c6668d8-56bjb</p>
- <p>Status: running</p>
-</div>
-
-<button type="button" mdbBtn color="default" rounded="true" data-toggle="modal" data-target="#basicExample"
- (click)="frame.show()" mdbWavesEffect>Edit Configuration</button>
-
-<div mdbModal #frame="mdbModal" class="modal fade left" id="frameModalTop" tabindex="-1" role="dialog"
- aria-labelledby="myModalLabel" aria-hidden="true" (opened)="onOpened($event)">
- <div class="modal-dialog modal-notify modal-info modal-side modal-top-left" role="document">
- <!--Content-->
- <div class="modal-content">
- <!--Header-->
- <div class="modal-header">
- <p class="heading lead">xApp Info</p>
-
- <button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="frame.hide()">
- <span aria-hidden="true" class="white-text">×</span>
- </button>
- </div>
-
- <!--Body-->
- <div class="modal-body">
-
- <img src="../../../assets/intelligence.png" alt=""
- class="img-fluid">
-
- <div class="text-center">
- <p>xApp Configuration</p>
- <div class="md-form">
- <textarea type="text" id="form8" class="md-textarea form-control" rows="1" mdbInput
- [formControl]="contactFormModalHelm"></textarea>
- <label data-error="wrong" data-success="right" for="form8">Delay</label>
- </div>
- <div class="md-form">
- <textarea type="text" id="form8" class="md-textarea form-control" rows="1" mdbInput
- [formControl]="contactFormModalHelm"></textarea>
- <label data-error="wrong" data-success="right" for="form8">Load</label>
- </div>
- </div>
- </div>
-
- <!--Footer-->
- <div class="modal-footer justify-content-center">
- <a type="button" mdbBtn color="primary" class="waves-effect" mdbWavesEffect>
- <mat-icon style="vertical-align: -21%;">launch</mat-icon> Update
- </a>
- <a type="button" mdbBtn color="primary" outline="true" class="waves-effect" mdbWavesEffect (click)="frame.hide()"
- data-dismiss="modal">
- <mat-icon style="vertical-align: -21%; size: 1em">close</mat-icon> Cancel</a>
- </div>
- </div>
- <!--/.Content-->
- </div>
-</div>
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 AT&T Intellectual Property and Nokia
- * %%
- * 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.
- * ========================LICENSE_END===================================
- */
-import { Component, Input, OnInit , Output, EventEmitter } from '@angular/core';
-import { FormControl, Validators } from '@angular/forms';
-import { ViewCell } from 'ng2-smart-table';
-
-@Component({
- selector: 'app-xapp',
- templateUrl: './xapp.component.html',
- styleUrls: ['./xapp.component.scss']
-})
-export class XappComponent implements ViewCell, OnInit {
-
- public renderValue;
-
- @Input() value;
- @Input() rowData: any;
- @Output() save: EventEmitter<any> = new EventEmitter();
- contactFormModalHelm = new FormControl('', Validators.required);
- onOpened(event: any) {
- console.log(event);
- this.rowData = event.data;
- }
-
-
- constructor() { }
-
- ngOnInit() {
- this.renderValue = this.value;
-
- }
-
- example() {
- alert(this.renderValue);
- }
-
- onDeployxApp() {
- this.save.emit(this.rowData);
- }
-
-
-}
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>1.0.3-SNAPSHOT</version>
+ <version>1.0.4-SNAPSHOT</version>
</parent>
<!-- This groupId will NOT allow deployment in LF -->
<groupId>org.o-ran-sc.ric.xappmgr.client</groupId>