First version of common policy edit dialog 47/5747/1
authorelinuxhenrik <henrik.b.andersson@est.tech>
Wed, 10 Mar 2021 16:15:32 +0000 (17:15 +0100)
committerelinuxhenrik <henrik.b.andersson@est.tech>
Wed, 10 Mar 2021 16:15:46 +0000 (17:15 +0100)
Change-Id: I63c579bd1374ad0f1c7b15b9a13d3b8869d3d558
Signed-off-by: elinuxhenrik <henrik.b.andersson@est.tech>
Issue-ID: NONRTRIC-463

12 files changed:
webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.html [deleted file]
webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.scss [deleted file]
webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.ts [deleted file]
webapp-frontend/src/app/policy/policy-control.component.ts
webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.html
webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.scss
webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.spec.ts [moved from webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.spec.ts with 74% similarity]
webapp-frontend/src/app/policy/policy-instance-dialog/policy-instance-dialog.component.ts
webapp-frontend/src/app/policy/policy-instance/policy-instance.component.ts
webapp-frontend/src/app/policy/policy.module.ts
webapp-frontend/src/app/policy/typed-policy-editor/typed-policy-editor.component.html
webapp-frontend/src/app/policy/typed-policy-editor/typed-policy-editor.component.ts

diff --git a/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.html b/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.html
deleted file mode 100644 (file)
index afba575..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--
-  ========================LICENSE_START=================================
-  O-RAN-SC
-  %%
-  Copyright (C) 2020 Nordix Foundation
-  %%
-  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 class="text-muted logo" fxLayout="row" fxLayoutGap="50px" fxLayoutAlign="space-around center">
-    <div id="instanceInfo" *ngIf="policyInstanceId">[{{this.ric}}] Instance ID: {{policyInstanceId}}</div>
-</div>
-<div class="mat-elevation-z8 header row" [ngClass]="{'header-dark': darkMode}">
-    <div class="logo">
-        <img src="assets/oran-logo.png" width="30px" height="30px" style="position: relative; z-index: 50" />
-        <svg class="logo__icon" viewBox="150.3 22.2 1000 50">
-            <text class="logo__text" [ngClass]="{'logo__text-dark': darkMode}" font-size="30" font-weight="600"
-                letter-spacing=".1em" transform="translate(149 56)">
-                <tspan *ngIf="!this.policyInstanceId">Create new policy instance of &lt; No type &gt;</tspan>
-            </text>
-        </svg>
-    </div>
-</div>
-
-<form [formGroup]="instanceForm" fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-sm="column"
-    fxLayoutAlign.lt-sm="flex-start center">
-
-    <mat-card class="card" [ngClass]="{'card-dark': darkMode}">
-        <nrcp-ric-selector *ngIf="!this.policyInstanceId" [instanceForm]="instanceForm"></nrcp-ric-selector>
-        <h4>
-            Properties
-        </h4>
-        <nrcp-no-type-policy-editor [policyJson]="this.policyJson" [instanceForm]="instanceForm"></nrcp-no-type-policy-editor>
-        <div mat-dialog-actions>
-            <button id="closeButton"  mat-raised-button [mat-dialog-close]="false">Close</button>
-            <button id="submitButton" mat-raised-button (click)="this.onSubmit()" class="submitBtn" [disabled]="!instanceForm.valid">
-                Submit
-            </button>
-        </div>
-    </mat-card>
-</form>
\ No newline at end of file
diff --git a/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.scss b/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.scss
deleted file mode 100644 (file)
index accb527..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * 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===================================
- */
-
-
-.logo__text {
-    fill: #2B244D;
-}
-
-.logo__text-dark {
-    fill: #ffffff;
-}
-
-.header-dark {
-    background: #2B244D;
-}
-
-.logo {
-    margin-left: 10px;
-}
-
-.logo__icon {
-    height: 2rem;
-    margin-left: 1rem;
-}
-
-.submitBtn {
-    background-color: #4CAF50;
-    /* Green */
-    margin-right: 10px;
-}
-
-.header {
-    background: linear-gradient(to bottom, white 0%, grayscale($color: #eeeaea) 100%);
-    font-size: 40px;
-    margin-top: 10px;
-    margin-bottom: 10px;
-    margin-left: 2px;
-    margin-right: 2px;
-}
-
-.header-dark {
-    background: #2B244D;
-}
-
-
-.card {
-    height: 100%;
-    width: 100%;
-    margin-left: 2px;
-    margin-right: 2px;
-    background-color: grayscale($color: #eeeaea);
-}
-
-.card-dark {
-    background-color: #1c1c24;
-}
diff --git a/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.ts b/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.ts
deleted file mode 100644 (file)
index 855d718..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * 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, Inject, OnInit, ViewChild } from '@angular/core';
-import { FormGroup } from '@angular/forms';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
-import { PolicyService } from '../../services/policy/policy.service';
-import { NotificationService } from '../../services/ui/notification.service';
-import { UiService } from '../../services/ui/ui.service';
-import { HttpErrorResponse } from '@angular/common/http';
-import { ErrorDialogService } from '../../services/ui/error-dialog.service';
-import * as uuid from 'uuid';
-import { CreatePolicyInstance } from '../../interfaces/policy.types';
-import { RicSelectorComponent } from '../ric-selector/ric-selector.component';
-import { formatJsonString, NoTypePolicyEditorComponent } from '../no-type-policy-editor/no-type-policy-editor.component';
-
-@Component({
-  selector: 'nrcp-no-type-policy-instance-dialog',
-  templateUrl: './no-type-policy-instance-dialog.component.html',
-  styleUrls: ['./no-type-policy-instance-dialog.component.scss']
-})
-export class NoTypePolicyInstanceDialogComponent implements OnInit {
-  instanceForm: FormGroup;
-  @ViewChild(RicSelectorComponent)
-  private ricSelectorComponent: RicSelectorComponent;
-  @ViewChild(NoTypePolicyEditorComponent)
-  private policyEditorComponent: NoTypePolicyEditorComponent;
-  policyInstanceId: string; // null if not yet created
-  policyJson: string;
-  darkMode: boolean;
-  ric: string;
-  allRicIds: string[] = [];
-
-  constructor(
-    public dialogRef: MatDialogRef<NoTypePolicyInstanceDialogComponent>,
-    private policySvc: PolicyService,
-    private errorService: ErrorDialogService,
-    private notificationService: NotificationService,
-    @Inject(MAT_DIALOG_DATA) private data,
-    private ui: UiService) {
-    this.policyInstanceId = data.instanceId;
-    this.policyJson = data.instanceJson ? formatJsonString(data.instanceJson) : '{}';
-    this.ric = data.ric;
-  }
-
-  ngOnInit() {
-    this.ui.darkModeState.subscribe((isDark) => {
-      this.darkMode = isDark;
-    });
-    this.instanceForm = new FormGroup({});
-  }
-
-  onSubmit() {
-    if (this.policyInstanceId == null) {
-      this.policyInstanceId = uuid.v4();
-    }
-    const self: NoTypePolicyInstanceDialogComponent = this;
-    let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(this.policyEditorComponent.policyJsonTextArea.value);
-    this.policySvc.putPolicy(createPolicyInstance).subscribe(
-      {
-        next(_) {
-          self.notificationService.success('Policy without type:' + self.policyInstanceId + ' submitted');
-          self.dialogRef.close();
-        },
-        error(error: HttpErrorResponse) {
-          self.errorService.displayError('Submit failed: ' + error.error);
-        },
-        complete() { }
-      });
-  }
-
-  private createPolicyInstance(policyJson: string): CreatePolicyInstance {
-    let createPolicyInstance = {} as CreatePolicyInstance;
-    createPolicyInstance.policy_data = JSON.parse(policyJson);
-    createPolicyInstance.policy_id = this.policyInstanceId;
-    createPolicyInstance.policytype_id = '';
-    createPolicyInstance.ric_id = this.ricSelectorComponent ? this.ricSelectorComponent.selectedRic : this.ric;
-    createPolicyInstance.service_id = 'controlpanel';
-    return createPolicyInstance;
-  }
-}
index 01c38b6..28253c8 100644 (file)
@@ -23,7 +23,6 @@ import { MatDialog } from '@angular/material/dialog';
 
 import { BehaviorSubject, Observable } from 'rxjs';
 
-import { NoTypePolicyInstanceDialogComponent } from './no-type-policy-instance-dialog/no-type-policy-instance-dialog.component';
 import { PolicyTypeSchema } from '../interfaces/policy.types';
 import { PolicyTypeDataSource } from './policy-type/policy-type.datasource';
 import { getPolicyDialogProperties } from './policy-instance-dialog/policy-instance-dialog.component';
@@ -67,14 +66,8 @@ export class PolicyControlComponent implements OnInit {
     }
 
     createPolicyInstance(policyTypeSchema: PolicyTypeSchema): void {
-        let dialogRef;
-        if (this.isSchemaEmpty(policyTypeSchema)) {
-            dialogRef = this.dialog.open(NoTypePolicyInstanceDialogComponent,
-                getPolicyDialogProperties(policyTypeSchema, null, this.darkMode));
-        } else {
-            dialogRef = this.dialog.open(PolicyInstanceDialogComponent,
-                getPolicyDialogProperties(policyTypeSchema, null, this.darkMode));
-        }
+        let dialogRef = this.dialog.open(PolicyInstanceDialogComponent,
+            getPolicyDialogProperties(policyTypeSchema, null, this.darkMode));
         const info: PolicyTypeInfo = this.getPolicyTypeInfo(policyTypeSchema);
         dialogRef.afterClosed().subscribe(
             (_) => {
@@ -88,10 +81,6 @@ export class PolicyControlComponent implements OnInit {
         info.isExpanded.next(!info.isExpanded.getValue());
     }
 
-    private isSchemaEmpty(policyTypeSchema: PolicyTypeSchema): boolean {
-        return policyTypeSchema.schemaObject === '{}';
-    }
-
     getPolicyTypeInfo(policyTypeSchema: PolicyTypeSchema): PolicyTypeInfo {
         let info: PolicyTypeInfo = this.policyTypeInfo.get(policyTypeSchema.name);
         if (!info) {
index 695dc6d..0b85c58 100644 (file)
@@ -2,7 +2,7 @@
   ========================LICENSE_START=================================
   O-RAN-SC
   %%
-  Copyright (C) 2019 Nordix Foundation
+  Copyright (C) 2020 Nordix Foundation
   %%
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
   -->
 
 <div class="text-muted logo" fxLayout="row" fxLayoutGap="50px" fxLayoutAlign="space-around center">
-    <div *ngIf="policyInstanceId">[{{ric}}] Instance ID: {{policyInstanceId}}</div>
+    <div id="instanceInfo" *ngIf="policyInstanceId">[{{this.ric}}] Instance ID: {{policyInstanceId}}</div>
 </div>
 <div class="mat-elevation-z8 header row" [ngClass]="{'header-dark': darkMode}">
     <div class="logo">
@@ -27,7 +27,7 @@
         <svg class="logo__icon" viewBox="150.3 22.2 1000 50">
             <text class="logo__text" [ngClass]="{'logo__text-dark': darkMode}" font-size="30" font-weight="600"
                 letter-spacing=".1em" transform="translate(149 56)">
-                <tspan *ngIf="!policyInstanceId">Create new policy instance of type </tspan>
+                <tspan *ngIf="!this.policyInstanceId">Create new policy instance of type</tspan>
                 <tspan *ngIf="jsonSchemaObject.title"> {{jsonSchemaObject.title}}</tspan>
                 <tspan *ngIf="!jsonSchemaObject.title"> {{policyTypeName}}</tspan>
             </text>
 
 <div class="text-muted" *ngIf="jsonSchemaObject.description">{{jsonSchemaObject.description}}</div>
 
-<div [formGroup]="instanceForm" fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-sm="column"
+<form [formGroup]="instanceForm" fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-sm="column"
     fxLayoutAlign.lt-sm="flex-start center">
 
     <mat-card class="card" [ngClass]="{'card-dark': darkMode}">
-        <mat-form-field *ngIf="!policyInstanceId" appearance="fill">
-            <mat-select id="ricSelector" formControlName="ricSelector" matInput required [(value)]="ric"
-                placeholder="Target"
-                matTooltip="Element where the policy instance resides, e.g. a gNodeB or Near-RT RIC">
-                <mat-option *ngFor="let ric of allRics" [value]="ric">
-                    {{ric.ric_id}}
-                </mat-option>
-            </mat-select>
-            <div *ngIf="ricSelector.invalid && (ricSelector.dirty || ricSelector.touched)">
-                <div *ngIf="ricSelector.errors.required">
-                    <mat-error role="alert">This field is required.</mat-error>
-                </div>
-            </div>
-        </mat-form-field>
-
-        <nrcp-typed-policy-editor [jsonSchemaObject]="jsonSchemaObject" [jsonObject]="data.instanceJson" [darkMode]="darkMode"></nrcp-typed-policy-editor>
-        <hr />
-        <button mat-raised-button (click)="onClose()">Close</button>
-        <button mat-raised-button (click)="onSubmit()" [disabled]="!isJsonFormValid || !ric"
-            class="submitBtn">Submit</button>
-        <hr />
+        <nrcp-ric-selector *ngIf="!policyInstanceId" [instanceForm]="instanceForm"></nrcp-ric-selector>
+        <h4 *ngIf="!typeHasSchema()">
+            Properties
+        </h4>
+        <nrcp-no-type-policy-editor *ngIf="!typeHasSchema()" [policyJson]="policyJson" [instanceForm]="instanceForm"></nrcp-no-type-policy-editor>
+        <nrcp-typed-policy-editor *ngIf="typeHasSchema()" [jsonSchemaObject]="jsonSchemaObject" [jsonObject]="policyJson" [darkMode]="darkMode"></nrcp-typed-policy-editor>
+        <div mat-dialog-actions>
+            <button id="closeButton"  mat-raised-button [mat-dialog-close]="false">Close</button>
+            <button id="submitButton" mat-raised-button (click)="onSubmit()" class="submitBtn" [disabled]="!isFormValid()">
+                Submit
+            </button>
+        </div>
     </mat-card>
-</div>
\ No newline at end of file
+</form>
\ No newline at end of file
index 7ecfff1..accb527 100644 (file)
     fill: #ffffff;
 }
 
-.text__dark {
-    color: white;
-}
-
-.header {
-    background: linear-gradient(to bottom, white 0%, grayscale($color: #eeeaea) 100%);
-    font-size: 40px;
-    margin-top: 10px;
-    margin-bottom: 10px;
-    margin-left: 2px;
-    margin-right: 2px;
-}
-
 .header-dark {
     background: #2B244D;
 }
     margin-right: 10px;
 }
 
+.header {
+    background: linear-gradient(to bottom, white 0%, grayscale($color: #eeeaea) 100%);
+    font-size: 40px;
+    margin-top: 10px;
+    margin-bottom: 10px;
+    margin-left: 2px;
+    margin-right: 2px;
+}
+
+.header-dark {
+    background: #2B244D;
+}
+
+
 .card {
     height: 100%;
     width: 100%;
@@ -69,4 +70,4 @@
 
 .card-dark {
     background-color: #1c1c24;
-}
\ No newline at end of file
+}
@@ -33,19 +33,19 @@ import { ToastrModule } from "ngx-toastr";
 import { PolicyService } from "../../services/policy/policy.service";
 import { ErrorDialogService } from "../../services/ui/error-dialog.service";
 import { UiService } from "../../services/ui/ui.service";
-import { NoTypePolicyInstanceDialogComponent } from "./no-type-policy-instance-dialog.component";
+import { PolicyInstanceDialogComponent } from "./policy-instance-dialog.component";
 import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
 
-describe('NoTypePolicyInstanceDialogComponent', () => {
-  let component: NoTypePolicyInstanceDialogComponent;
-  let fixture: ComponentFixture<NoTypePolicyInstanceDialogComponent>;
+describe('PolicyInstanceDialogComponent', () => {
+  let component: PolicyInstanceDialogComponent;
+  let fixture: ComponentFixture<PolicyInstanceDialogComponent>;
   let loader: HarnessLoader;
   let policyServiceSpy: jasmine.SpyObj<PolicyService>;
   let errDialogServiceSpy: jasmine.SpyObj<ErrorDialogService>;
 
   beforeEach(async () => {
-    policyServiceSpy = jasmine.createSpyObj('PolicyService', [ 'putPolicy' ]);
-    errDialogServiceSpy = jasmine.createSpyObj('ErrorDialogService', [ 'displayError' ]);
+    policyServiceSpy = jasmine.createSpyObj('PolicyService', ['putPolicy']);
+    errDialogServiceSpy = jasmine.createSpyObj('ErrorDialogService', ['displayError']);
 
     TestBed.configureTestingModule({
       imports: [
@@ -61,7 +61,7 @@ describe('NoTypePolicyInstanceDialogComponent', () => {
         CUSTOM_ELEMENTS_SCHEMA
       ],
       declarations: [
-        NoTypePolicyInstanceDialogComponent
+        PolicyInstanceDialogComponent
       ],
       providers: [
         { provide: MatDialogRef, useValue: component },
@@ -73,8 +73,12 @@ describe('NoTypePolicyInstanceDialogComponent', () => {
     });
   });
 
-  describe('content when creating policy', () => {
+  describe('content when creating policy without type', () => {
     beforeEach(async () => {
+      const policyData = {
+        createSchema: '{}'
+      };
+      TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
       ({ fixture, component, loader } = compileAndGetComponents(fixture, component, loader));
     });
 
@@ -83,7 +87,7 @@ describe('NoTypePolicyInstanceDialogComponent', () => {
       expect(ele.src).toContain('assets/oran-logo.png');
 
       ele = fixture.debugElement.nativeElement.querySelector('text');
-      expect(ele.childNodes[0].childNodes[0].textContent).toEqual('Create new policy instance of < No type >');
+      expect(ele.textContent).toEqual('Create new policy instance of type < No Type >');
 
       ele = fixture.debugElement.nativeElement.querySelector('#instanceInfo');
       expect(ele).toBeFalsy();
@@ -106,35 +110,35 @@ describe('NoTypePolicyInstanceDialogComponent', () => {
       expect(await closeButton.isDisabled()).toBeFalsy();
       expect(await closeButton.getText()).toEqual('Close');
 
-      let submitButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#submitButton'}));
+      let submitButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({ selector: '#submitButton' }));
       // expect(await submitButton.isDisabled()).toBeTruthy();
       expect(await submitButton.getText()).toEqual('Submit');
     });
   });
 
-  describe('content when editing policy', () => {
+  describe('content when editing policy without type', () => {
     beforeEach(async () => {
       const policyData = {
-        createSchema: "{}",
-        instanceId: "instanceId",
+        createSchema: '{}',
+        instanceId: 'instanceId',
         instanceJson: '{"qosObjectives": {"priorityLevel": 3100}}',
-        name: "name",
-        ric: "ric1"
-    };
-      TestBed.overrideProvider(MAT_DIALOG_DATA, {useValue: policyData }); // Should be provided with a policy
+        name: 'name',
+        ric: 'ric1'
+      };
+      TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: policyData }); // Should be provided with a policy
       ({ fixture, component, loader } = compileAndGetComponents(fixture, component, loader));
     });
 
     it('should contain oran logo and instance info', async () => {
-        let ele = fixture.debugElement.nativeElement.querySelector('img');
-        expect(ele.src).toContain('assets/oran-logo.png');
+      let ele = fixture.debugElement.nativeElement.querySelector('img');
+      expect(ele.src).toContain('assets/oran-logo.png');
 
-        ele = fixture.debugElement.nativeElement.querySelector('text');
-        expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
+      ele = fixture.debugElement.nativeElement.querySelector('text');
+      expect(ele.childNodes[0].childNodes[0]).toBeFalsy(); // No create title
 
-        ele = fixture.debugElement.nativeElement.querySelector('#instanceInfo');
-        expect(ele).toBeTruthy();
-        expect(ele.innerText).toEqual('[ric1] Instance ID: instanceId');
+      ele = fixture.debugElement.nativeElement.querySelector('#instanceInfo');
+      expect(ele).toBeTruthy();
+      expect(ele.innerText).toEqual('[ric1] Instance ID: instanceId');
     });
 
     it('should not contain ric select', async () => {
@@ -148,11 +152,11 @@ describe('NoTypePolicyInstanceDialogComponent', () => {
     });
 
     it('should contain enabled Close and Submit buttons', async () => {
-      let closeButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#closeButton'}));
+      let closeButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({ selector: '#closeButton' }));
       expect(await closeButton.isDisabled()).toBeFalsy();
       expect(await closeButton.getText()).toEqual('Close');
 
-      let submitButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#submitButton'}));
+      let submitButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({ selector: '#submitButton' }));
       expect(await submitButton.isDisabled()).toBeFalsy();
       expect(await submitButton.getText()).toEqual('Submit');
     });
@@ -160,10 +164,10 @@ describe('NoTypePolicyInstanceDialogComponent', () => {
   });
 });
 
-function compileAndGetComponents(fixture: ComponentFixture<NoTypePolicyInstanceDialogComponent>, component: NoTypePolicyInstanceDialogComponent, loader: HarnessLoader) {
+function compileAndGetComponents(fixture: ComponentFixture<PolicyInstanceDialogComponent>, component: PolicyInstanceDialogComponent, loader: HarnessLoader) {
   TestBed.compileComponents();
 
-  fixture = TestBed.createComponent(NoTypePolicyInstanceDialogComponent);
+  fixture = TestBed.createComponent(PolicyInstanceDialogComponent);
   component = fixture.componentInstance;
   fixture.detectChanges();
   loader = TestbedHarnessEnvironment.loader(fixture);
index 12b2f94..56c3a11 100644 (file)
@@ -2,7 +2,7 @@
  * ========================LICENSE_START=================================
  * O-RAN-SC
  * %%
- * Copyright (C) 2019 Nordix Foundation
+ * Copyright (C) 2020 Nordix Foundation
  * %%
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * ========================LICENSE_END===================================
  */
 import { Component, Inject, OnInit, ViewChild } from '@angular/core';
+import { FormGroup } from '@angular/forms';
 import { MatDialogConfig, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
-import * as uuid from 'uuid';
-import { CreatePolicyInstance, PolicyInstance, PolicyTypeSchema } from '../../interfaces/policy.types';
 import { PolicyService } from '../../services/policy/policy.service';
-import { ErrorDialogService } from '../../services/ui/error-dialog.service';
-import { NotificationService } from './../../services/ui/notification.service';
+import { NotificationService } from '../../services/ui/notification.service';
 import { UiService } from '../../services/ui/ui.service';
 import { HttpErrorResponse } from '@angular/common/http';
-import { FormGroup, FormControl, Validators } from '@angular/forms';
-import { Ric, Rics } from '../../interfaces/ric';
+import { ErrorDialogService } from '../../services/ui/error-dialog.service';
+import * as uuid from 'uuid';
+import { CreatePolicyInstance, PolicyInstance, PolicyTypeSchema } from '../../interfaces/policy.types';
+import { RicSelectorComponent } from '../ric-selector/ric-selector.component';
+import { formatJsonString, NoTypePolicyEditorComponent } from '../no-type-policy-editor/no-type-policy-editor.component';
 import { TypedPolicyEditorComponent } from '../typed-policy-editor/typed-policy-editor.component';
 
-
 @Component({
-    selector: 'nrcp-policy-instance-dialog',
-    templateUrl: './policy-instance-dialog.component.html',
-    styleUrls: ['./policy-instance-dialog.component.scss']
+  selector: 'nrcp-policy-instance-dialog',
+  templateUrl: './policy-instance-dialog.component.html',
+  styleUrls: ['./policy-instance-dialog.component.scss']
 })
 export class PolicyInstanceDialogComponent implements OnInit {
-    @ViewChild(TypedPolicyEditorComponent)
-    policyEditor: TypedPolicyEditorComponent;
-    instanceForm: FormGroup;
+  instanceForm: FormGroup;
+  @ViewChild(RicSelectorComponent)
+  ricSelector: RicSelectorComponent;
+  @ViewChild(NoTypePolicyEditorComponent)
+  noTypePolicyEditor: NoTypePolicyEditorComponent;
+  @ViewChild(TypedPolicyEditorComponent)
+  typedPolicyEditor: TypedPolicyEditorComponent;
+  policyInstanceId: string; // null if not yet created
+  policyJson: string;
+  policyTypeName: string;
+  jsonSchemaObject: any = {};
+  darkMode: boolean;
+  ric: string;
+  allRicIds: string[] = [];
 
+  constructor(
+    public dialogRef: MatDialogRef<PolicyInstanceDialogComponent>,
+    private policySvc: PolicyService,
+    private errorService: ErrorDialogService,
+    private notificationService: NotificationService,
+    @Inject(MAT_DIALOG_DATA) private data,
+    private ui: UiService) {
+    this.policyInstanceId = data.instanceId;
+    this.policyTypeName = data.name ? data.name : '< No Type >';
+    this.policyJson = data.instanceJson;
+    this.jsonSchemaObject = data.createSchema;
+    this.ric = data.ric;
+  }
 
-    ric: string;
-    allRics: Ric[];
-    policyInstanceId: string; // null if not yet created
-    policyTypeName: string;
-    jsonSchemaObject: any = {};
-    darkMode: boolean;
+  ngOnInit() {
+    this.ui.darkModeState.subscribe((isDark) => {
+      this.darkMode = isDark;
+    });
+    this.instanceForm = new FormGroup({});
+    this.formatNoTypePolicyJson();
+  }
 
-    private fetchRics() {
-        console.log('fetchRics ' + this.policyTypeName);
-        const self: PolicyInstanceDialogComponent = this;
-        this.dataService.getRics(this.policyTypeName).subscribe(
-            {
-                next(value: Rics) {
-                    self.allRics = value.rics;
-                    console.log(value);
-                }
-            });
+  private formatNoTypePolicyJson() {
+    if (!this.typeHasSchema()) {
+      if (this.policyJson) {
+        this.policyJson = formatJsonString(this.policyJson);
+      } else {
+        this.policyJson = '{}';
+      }
     }
+  }
 
-    constructor(
-        private dataService: PolicyService,
-        private errorService: ErrorDialogService,
-        private notificationService: NotificationService,
-        @Inject(MAT_DIALOG_DATA) public data,
-        private dialogRef: MatDialogRef<PolicyInstanceDialogComponent>,
-        private ui: UiService) {
-        this.policyInstanceId = data.instanceId;
-        this.policyTypeName = data.name;
-        this.jsonSchemaObject = data.createSchema;
-        this.ric = data.ric;
+  onSubmit() {
+    if (this.policyInstanceId == null) {
+      this.policyInstanceId = uuid.v4();
     }
-
-    ngOnInit() {
-        this.ui.darkModeState.subscribe((isDark) => {
-            this.darkMode = isDark;
-        });
-        this.instanceForm = new FormGroup({
-            'ricSelector': new FormControl(this.ric, [
-                Validators.required
-            ])
-        });
-        if (!this.policyInstanceId) {
-            this.fetchRics();
-        }
+    const self: PolicyInstanceDialogComponent = this;
+    let policyData: string;
+    if (this.typeHasSchema()) {
+      policyData = this.typedPolicyEditor.prettyLiveFormData;
+    } else {
+      policyData = this.noTypePolicyEditor.policyJsonTextArea.value;
     }
+    let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(policyData);
+    this.policySvc.putPolicy(createPolicyInstance).subscribe(
+      {
+        next(_) {
+          self.notificationService.success('Policy without type:' + self.policyInstanceId + ' submitted');
+          self.dialogRef.close();
+        },
+        error(error: HttpErrorResponse) {
+          self.errorService.displayError('Submit failed: ' + error.error);
+        },
+        complete() { }
+      });
+  }
 
-    get ricSelector() { return this.instanceForm.get('ricSelector'); }
+  typeHasSchema(): boolean {
+    return this.jsonSchemaObject !== '{}';
+  }
 
-    onSubmit() {
-        if (this.policyInstanceId == null) {
-            this.policyInstanceId = uuid.v4();
-        }
-        const policyJson: string = this.policyEditor.prettyLiveFormData;
-        const self: PolicyInstanceDialogComponent = this;
-        let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(policyJson);
-        this.dataService.putPolicy(createPolicyInstance).subscribe(
-            {
-                next(_) {
-                    self.notificationService.success('Policy ' + self.policyTypeName + ':' + self.policyInstanceId +
-                        ' submitted');
-                    self.dialogRef.close();
-                },
-                error(error: HttpErrorResponse) {
-                    self.errorService.displayError('Submit failed: ' + error.error);
-                },
-                complete() { }
-            });
+  isFormValid(): boolean {
+    let isValid: boolean = this.instanceForm.valid;
+    if (this.typeHasSchema()) {
+      isValid = isValid && this.typedPolicyEditor ? this.typedPolicyEditor.formIsValid : false;
     }
+    return isValid;
+  }
 
-    private createPolicyInstance(policyJson: string) {
-        let createPolicyInstance = {} as CreatePolicyInstance;
-        createPolicyInstance.policy_data = JSON.parse(policyJson);
-        createPolicyInstance.policy_id = this.policyInstanceId;
-        createPolicyInstance.policytype_id = this.policyTypeName;
-        createPolicyInstance.ric_id = (!this.ricSelector.value.ric_id) ? this.ric : this.ricSelector.value.ric_id;
-        createPolicyInstance.service_id = 'controlpanel';
-        return createPolicyInstance;
-    }
-
-    onClose() {
-        this.dialogRef.close();
-    }
-
-    get isJsonFormValid(): boolean {
-        return this.policyEditor ? this.policyEditor.formIsValid : false;
-    }
+  private createPolicyInstance(policyJson: string): CreatePolicyInstance {
+    let createPolicyInstance = {} as CreatePolicyInstance;
+    createPolicyInstance.policy_data = JSON.parse(policyJson);
+    createPolicyInstance.policy_id = this.policyInstanceId;
+    createPolicyInstance.policytype_id = '';
+    createPolicyInstance.ric_id = this.ricSelector ? this.ricSelector.selectedRic : this.ric;
+    createPolicyInstance.service_id = 'controlpanel';
+    return createPolicyInstance;
+  }
 }
 
 export function getPolicyDialogProperties(policyTypeSchema: PolicyTypeSchema, instance: PolicyInstance, darkMode: boolean): MatDialogConfig {
-    const createSchema = policyTypeSchema.schemaObject;
-    const instanceId = instance ? instance.policy_id : null;
-    const instanceJson = instance ? instance.policy_data : null;
-    const name = policyTypeSchema.name;
-    const ric = instance ? instance.ric_id : null;
-    return {
-        maxWidth: '1200px',
-        maxHeight: '900px',
-        width: '900px',
-        role: 'dialog',
-        disableClose: false,
-        panelClass: darkMode ? 'dark-theme' : '',
-        data: {
-            createSchema,
-            instanceId,
-            instanceJson,
-            name,
-            ric
-        }
-    };
-}
-
+  const createSchema = policyTypeSchema.schemaObject;
+  const instanceId = instance ? instance.policy_id : null;
+  const instanceJson = instance ? instance.policy_data : null;
+  const name = policyTypeSchema.name;
+  const ric = instance ? instance.ric_id : null;
+  return {
+      maxWidth: '1200px',
+      maxHeight: '900px',
+      width: '900px',
+      role: 'dialog',
+      disableClose: false,
+      panelClass: darkMode ? 'dark-theme' : '',
+      data: {
+          createSchema,
+          instanceId,
+          instanceJson,
+          name,
+          ric
+      }
+  };
+}
\ No newline at end of file
index 95313d0..0f34c43 100644 (file)
@@ -28,7 +28,6 @@ import { NotificationService } from '../../services/ui/notification.service';
 import { PolicyService } from '../../services/policy/policy.service';
 import { ConfirmDialogService } from '../../services/ui/confirm-dialog.service';
 import { PolicyInstance } from '../../interfaces/policy.types';
-import { NoTypePolicyInstanceDialogComponent } from '../no-type-policy-instance-dialog/no-type-policy-instance-dialog.component';
 import { PolicyInstanceDialogComponent } from '../policy-instance-dialog/policy-instance-dialog.component';
 import { getPolicyDialogProperties } from '../policy-instance-dialog/policy-instance-dialog.component';
 import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
@@ -84,24 +83,13 @@ export class PolicyInstanceComponent implements OnInit, AfterViewInit {
         this.policySvc.getPolicyInstance(instance.policy_id).subscribe(
             (refreshedJson: any) => {
                 instance = refreshedJson;
-                if (this.isSchemaEmpty()) {
-                    this.dialog.open(
-                        NoTypePolicyInstanceDialogComponent,
-                        getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe(
-                            (_: any) => {
-                                this.instanceDataSource.getPolicyInstances();
-                            }
-                        );
-                } else {
-                    this.dialog.open(
-                        PolicyInstanceDialogComponent,
-                        getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe(
-                            (_: any) => {
-                                this.instanceDataSource.getPolicyInstances();
-                            }
-                        );
-
-                }
+                this.dialog.open(
+                    PolicyInstanceDialogComponent,
+                    getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe(
+                        (_: any) => {
+                            this.instanceDataSource.getPolicyInstances();
+                        }
+                    );
             },
             (httpError: HttpErrorResponse) => {
                 this.notificationService.error('Could not refresh instance. Please try again.' + httpError.message);
index 5f7e4fc..d4a4b1e 100644 (file)
@@ -23,7 +23,6 @@ import { NgModule } from '@angular/core';
 import { MatTableModule } from '@angular/material/table';
 import { PolicyCardComponent } from './policy-card/policy-card.component';
 import { PolicyControlComponent } from './policy-control.component';
-import { NoTypePolicyInstanceDialogComponent } from './no-type-policy-instance-dialog/no-type-policy-instance-dialog.component';
 import { PolicyInstanceDialogComponent } from './policy-instance-dialog/policy-instance-dialog.component';
 import { PolicyInstanceComponent } from './policy-instance/policy-instance.component';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -52,8 +51,8 @@ import { MaterialDesignFrameworkModule } from 'angular6-json-schema-form';
 import { FlexLayoutModule } from '@angular/flex-layout';
 import { Routes, RouterModule } from '@angular/router';
 import { RicSelectorComponent } from './ric-selector/ric-selector.component';
-import { NoTypePolicyEditorComponent } from './no-type-policy-editor/no-type-policy-editor.component';
 import { TypedPolicyEditorComponent } from './typed-policy-editor/typed-policy-editor.component';
+import { NoTypePolicyEditorComponent } from './no-type-policy-editor/no-type-policy-editor.component';
 
 const routes:Routes = [
   {path: 'policy', component: PolicyControlComponent}
@@ -61,7 +60,6 @@ const routes:Routes = [
 
 @NgModule({
   declarations: [
-    NoTypePolicyInstanceDialogComponent,
     PolicyCardComponent,
     PolicyControlComponent,
     PolicyInstanceComponent,
index ecbfd15..6b8c233 100644 (file)
@@ -25,9 +25,7 @@
     Properties
 </h4>
 <div id="propertiesDiv" *ngIf="isVisible.form" class="json-schema-form" [@expandSection]="true">
-    <div *ngIf="!formActive">{{jsonFormStatusMessage}}</div>
-
-    <json-schema-form id="json-schema-form" *ngIf="formActive" [form]="jsonSchemaObject"
+    <json-schema-form id="json-schema-form" [form]="jsonSchemaObject"
         [(data)]="jsonObject" [options]="jsonFormOptions" [framework]="'material-design'" [language]="'en'"
         (onChanges)="onChanges($event)" (isValid)="isValid($event)"
         (validationErrors)="validationErrors($event)">
index 5a99e39..46b51bf 100644 (file)
@@ -59,19 +59,13 @@ export class TypedPolicyEditorComponent implements OnInit {
         json: false,
         schema: false
     };
-    formActive: boolean = false;
-    jsonFormStatusMessage: string = 'Loading form...';
     liveFormData: any = {};
     formIsValid: boolean = false;
     formValidationErrors: any;
 
-    constructor() {
-        this.formActive = false;
-    }
+    constructor() {}
 
-    ngOnInit(): void {
-         this.formActive = true;
-    }
+    ngOnInit(): void {}
 
     public onChanges(formData: any) {
         this.liveFormData = formData;