Input validations RAN Connect 40/140/4
authorSarkar, Anand (as0481) <as0481@att.com>
Sun, 12 May 2019 15:45:48 +0000 (11:45 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Mon, 13 May 2019 14:43:15 +0000 (10:43 -0400)
Change-Id: I83862860053c0a75ccc4dbf15cedfc47714cbb3a
Issue-Id: RICPLT-1277
Signed-off-by: Sarkar, Anand (as0481) <as0481@att.com>
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
docs/release-notes.rst
webapp-frontend/src/app/app.module.ts
webapp-frontend/src/app/signal/signal.component.ranconnect-dialog.html
webapp-frontend/src/app/signal/signal.component.ts

index 8e42eac..e1b87fb 100644 (file)
 RIC Dashboard Release Notes
 ===========================
 
-Version 1.0.2, 10 May 2019
+Version 1.0.2, 13 May 2019
 --------------------------
 * Update A1 mediator client to version 0.4.0
 * Add E2 response message with timestamp and status code
 * Fetch xAPP instance status information from xAPP Manager and display in dashboard
 * Allow the user to initiate an E2 (X2) connection between RIC and gNB/eNB
+* User input validations on connections between RIC and eNB/gNB in the dashboard
 * Add ANR xApp backend with mock implementation
 
 Version 1.0.1, 6 May 2019
index 19d6856..a978350 100644 (file)
@@ -32,20 +32,20 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms';
 import { AppRoutingModule } from './app-routing.module';
 import { AppComponent } from './app.component';
 import { LoginComponent } from './login/login.component';
-import { CatalogComponent, AppCatalogDeployDialog, } from './catalog/catalog.component';
-import { UiService} from './services/ui/ui.service';
-import { AdminService} from './services/admin/admin.service';
-import { CatalogService} from './services/catalog/catalog.service';
-import { ControlService} from './services/control/control.service';
-import { SignalService} from './services/signal/signal.service';
+import { CatalogComponent, AppCatalogDeployDialog } from './catalog/catalog.component';
+import { UiService } from './services/ui/ui.service';
+import { AdminService } from './services/admin/admin.service';
+import { CatalogService } from './services/catalog/catalog.service';
+import { ControlService } from './services/control/control.service';
+import { SignalService } from './services/signal/signal.service';
 import { SidenavListComponent } from './navigation/sidenav-list/sidenav-list.component';
 import { ControlComponent } from './control/control.component';
-import { SignalComponent, AppRANConnectDialog} from './signal/signal.component';
+import { SignalComponent, AppRANConnectDialog } from './signal/signal.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 { 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';
index 715943c..25b1a28 100644 (file)
     Setup RAN Connection
 </div>
 
-<div mat-dialog-content>
-  <mat-form-field class="input-display-block">
-    <input matInput placeholder="eNB/gNB Name" [(ngModel)]="data.ranName">
-  </mat-form-field>
-  <mat-form-field class="input-display-block">
-    <input matInput placeholder="IP" [(ngModel)]="data.ranIp">
-  </mat-form-field>
-  <mat-form-field class="input-display-block">
-    <input matInput placeholder="Port" [(ngModel)]="data.ranPort">
-  </mat-form-field>
-</div>
- <div mat-dialog-actions class="modal-footer justify-content-center">
-  <button class="mat-raised-button" (click)="close()">Cancel</button> 
-  <button class="mat-raised-button mat-primary" (click)="connectRAN()">Connect</button>
-</div>
+<form [formGroup]="ranDialogForm" novalidate autocomplete="off">
+  <div mat-dialog-content>
+    <mat-form-field class="input-display-block">
+      <input matInput type="text" placeholder="eNB/gNB Name" [(ngModel)]="data.ranName" formControlName="ranName">
+      <mat-hint align="end">Not more then 50 characters long.</mat-hint>
+      <mat-error *ngIf="validateControl('ranName') && hasError('ranName', 'required')">Name is required</mat-error>
+      <mat-error *ngIf="hasError('ranName', 'length')">Valid name is required</mat-error>
+    </mat-form-field>
+    <mat-form-field class="input-display-block">
+      <input matInput type="text" placeholder="IP" [(ngModel)]="data.ranIp" formControlName="ranIp">
+      <mat-error *ngIf="validateControl('ranIp') && hasError('ranIp', 'required')">IP is required</mat-error>
+      <mat-error *ngIf="hasError('ranIp', 'pattern')">Valid IP is required</mat-error>
+    </mat-form-field>
+    <mat-form-field class="input-display-block">
+      <input matInput type="text" placeholder="Port" [(ngModel)]="data.ranPort" formControlName="ranPort">
+      <mat-error *ngIf="validateControl('ranPort') && hasError('ranPort', 'required')">Port is required</mat-error>
+      <mat-error *ngIf="hasError('ranPort', 'pattern')">Valid port number is required</mat-error>
+    </mat-form-field>
+  </div>
+  <div mat-dialog-actions class="modal-footer justify-content-center">
+    <button class="mat-raised-button" (click)="close()">Cancel</button>
+    <button class="mat-raised-button mat-primary"
+      [disabled]="(validateControl('ranName') && hasError('ranName', 'required'))
+      || (validateControl('ranIp') && hasError('ranIp', 'required'))
+      || (validateControl('ranPort') && hasError('ranPort', 'required'))
+      || hasError('ranName', 'maxlength')
+      || hasError('ranIp', 'pattern')
+      || hasError('ranPort', 'pattern')
+      || (!data.ranName || !data.ranIp || !data.ranPort)"
+       (click)="connectRAN()">Connect</button>
+  </div>
+</form>
index a3ad5a2..e19f97c 100644 (file)
@@ -22,8 +22,8 @@ import { LocalDataSource } from 'ng2-smart-table';
 import { SignalService } from '../services/signal/signal.service';
 import { Router } from '@angular/router';
 import { MatDialog, MatDialogConfig, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
-import {MatFormFieldModule} from '@angular/material';
-import { FormGroup, FormControl, FormBuilder } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material';
+import { FormGroup, FormControl, FormBuilder, ReactiveFormsModule, Validators} from '@angular/forms';
 import { HttpClient } from '@angular/common/http';
 import { Observable } from 'rxjs/Rx';
 
@@ -38,8 +38,8 @@ export interface DialogData {
     templateUrl: 'signal.component.html',
     styleUrls: ['signal.component.css']
 })
-export class SignalComponent {
 
+export class SignalComponent {
     settings = {
         hideSubHeader: true,
         actions: {
@@ -116,7 +116,22 @@ export class AppRANConnectDialog implements OnInit {
           @Inject(MAT_DIALOG_DATA) public data: DialogData) {
     }
 
+    public ranDialogForm: FormGroup;
+
+        public ranName: string;
+
+        public ranIp: number;
+
+        public ranPort: number;
+
     ngOnInit() {
+        const ipPattern = '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))';
+        const portPattern = '^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$';
+        this.ranDialogForm = new FormGroup({
+                ranName: new FormControl('', [Validators.required, Validators.maxLength(50)]),
+                ranIp: new FormControl('', [Validators.required, Validators.pattern(ipPattern)]),
+                ranPort: new FormControl('', [Validators.required, Validators.pattern(portPattern)])
+            });
     }
 
     close() {
@@ -128,4 +143,15 @@ export class AppRANConnectDialog implements OnInit {
         this.dialogRef.close();
     }
 
+    public hasError(controlName: string, errorName: string) {
+        if (this.ranDialogForm.controls[controlName].hasError(errorName))
+            return true;
+        return false;
+    }
+
+  public validateControl(controlName: string) {
+        if (this.ranDialogForm.controls[controlName].invalid && this.ranDialogForm.controls[controlName].touched)
+            return true;
+        return false;
+    }
 }