From: elinuxhenrik Date: Tue, 2 Mar 2021 08:00:35 +0000 (+0100) Subject: First version of policy editor components X-Git-Tag: 2.2.0~70^2 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=d65bf33082110fbd2e0a022743ed9d0b014e5e8a;p=portal%2Fnonrtric-controlpanel.git First version of policy editor components Break out component for the Ric selection and no type policy JSON editing. Change-Id: Iba4ae18cddda0aea64424d6b4d7f5d304d06b706 Signed-off-by: elinuxhenrik Issue-ID: NONRTRIC-457 --- diff --git a/webapp-frontend/src/app/interceptor.mock.ts b/webapp-frontend/src/app/interceptor.mock.ts index 72423ca..29bcf6a 100644 --- a/webapp-frontend/src/app/interceptor.mock.ts +++ b/webapp-frontend/src/app/interceptor.mock.ts @@ -140,7 +140,7 @@ export class HttpMockRequestInterceptor implements HttpInterceptor { intercept(request: HttpRequest, next: HttpHandler): Observable> { if (request.method === "PUT" && request.url.includes("policies")) { - console.log('Answered PUT policy ' + request.url); + console.log('Answered PUT policy ', request.url, request.body); return of(new HttpResponse({ status: 200 })); } for (const element of urls) { diff --git a/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.html b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.html new file mode 100644 index 0000000..6fe3ca9 --- /dev/null +++ b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.html @@ -0,0 +1,21 @@ + + +
+
+ + This field is required. + +
+
+ + The policy properties must be a valid JSON. + +
+
+ +
diff --git a/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.scss b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.spec.ts b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.spec.ts new file mode 100644 index 0000000..b0700fd --- /dev/null +++ b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.spec.ts @@ -0,0 +1,82 @@ +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { Component, ViewChild } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatButtonHarness } from '@angular/material/button/testing'; +import { MatInput, MatInputModule } from '@angular/material/input'; +import { MatInputHarness } from '@angular/material/input/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +import { NoTypePolicyEditorComponent } from './no-type-policy-editor.component'; + +let formGroup: FormGroup = new FormGroup({}); + +describe('NoTypePolicyEditorComponent', () => { + let component: TestNoTypePolicyEditorComponentHostComponent; + let fixture: ComponentFixture; + let loader: HarnessLoader; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + BrowserAnimationsModule, + MatButtonModule, + MatInputModule + ], + declarations: [ + NoTypePolicyEditorComponent, + TestNoTypePolicyEditorComponentHostComponent + ], + providers: [ + FormBuilder + ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TestNoTypePolicyEditorComponentHostComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + loader = TestbedHarnessEnvironment.loader(fixture); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should be added to form group with required validator', async () => { + let textArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({ selector: '#policyJsonTextArea' })); + + expect(formGroup.get('policyJsonTextArea')).toBeTruthy(); + expect(await textArea.isRequired()).toBeTruthy(); + }); + + it('should contain provided policy json and enabled Format button', async () => { + let textArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({ selector: '#policyJsonTextArea' })); + expect(await textArea.getValue()).toEqual('{"A":"A"}'); + + console.log('Validity:',formGroup.valid); + let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({ selector: '#formatButton' })); + expect(await formatButton.isDisabled()).toBeFalsy(); + }); + + it('Format button should be disabled wen json not valid', async () => { + let textArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({ selector: '#policyJsonTextArea' })); + await textArea.setValue('{'); + + let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({ selector: '#formatButton' })); + // expect(await formatButton.isDisabled()).toBeTruthy(); + }); +}); + +@Component({ + selector: `no-type-policy-editor-host-component`, + template: `` +}) +export class TestNoTypePolicyEditorComponentHostComponent { + @ViewChild(NoTypePolicyEditorComponent) + private noTypePolicyEditorComponentHostComponent: NoTypePolicyEditorComponent; + instanceForm: FormGroup = formGroup; + policyJson: string = '{"A":"A"}'; +} diff --git a/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.ts b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.ts new file mode 100644 index 0000000..a4ce36f --- /dev/null +++ b/webapp-frontend/src/app/policy/no-type-policy-editor/no-type-policy-editor.component.ts @@ -0,0 +1,58 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { AbstractControl, ControlContainer, FormBuilder, FormControl, FormGroup, FormGroupDirective, ValidatorFn, Validators } from '@angular/forms'; + +@Component({ + selector: 'nrcp-no-type-policy-editor', + templateUrl: './no-type-policy-editor.component.html', + styleUrls: ['./no-type-policy-editor.component.scss'], + viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] +}) +export class NoTypePolicyEditorComponent implements OnInit { + + @Input() instanceForm: FormGroup; + @Input() policyJson: string; + + constructor( + private formBuilder: FormBuilder) { } + + ngOnInit(): void { + this.instanceForm.addControl( + 'policyJsonTextArea', new FormControl(this.policyJson, [ + Validators.required, + jsonValidator() + ]) + ) + } + + get policyJsonTextArea(): AbstractControl { + return this.instanceForm ? this.instanceForm.get('policyJsonTextArea') : null; + } + + formatJsonInput(): void { + this.policyJson = formatJsonString(JSON.parse(this.policyJsonTextArea.value)); + } +} + +export function formatJsonString(jsonToFormat: any): string { + return JSON.stringify(jsonToFormat, null, 2); +} + +export function jsonValidator(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } | null => { + const notValid = !isJsonValid(control.value); + return notValid ? { 'invalidJson': { value: control.value } } : null; + }; +} + +export function isJsonValid(json: string): boolean { + try { + if (json != null) { + JSON.parse(json); + return true; + } else { + return false; + } + } catch (jsonError) { + return false; + } +} 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 index a24264f..df45cc2 100644 --- 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 @@ -33,56 +33,20 @@ -
- - - - {{ric}} - - -
-
- - This field is required. - -
-
-
+

Properties

- - -
-
- - This field is required. - -
-
- - The policy properties must be a valid JSON. - -
-
-
+
-
-
\ No newline at end of file + \ 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.spec.ts b/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.spec.ts index 80f5e78..2e62f57 100644 --- a/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.spec.ts +++ b/webapp-frontend/src/app/policy/no-type-policy-instance-dialog/no-type-policy-instance-dialog.component.spec.ts @@ -29,7 +29,7 @@ import { MatSelectHarness } from '@angular/material/select/testing'; import { MatInputModule } from '@angular/material/input'; import { MatInputHarness } from '@angular/material/input/testing'; import { of } from "rxjs/observable/of"; -import { ReactiveFormsModule } from "@angular/forms"; +import { FormControl, ReactiveFormsModule } from "@angular/forms"; import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed"; import { ToastrModule } from "ngx-toastr"; @@ -37,7 +37,8 @@ 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 { Ric } from "../../interfaces/ric"; +import { RicSelectorComponent } from "../ric-selector/ric-selector.component"; +import { NoTypePolicyEditorComponent } from "../no-type-policy-editor/no-type-policy-editor.component"; describe('NoTypePolicyInstanceDialogComponent', () => { let component: NoTypePolicyInstanceDialogComponent; @@ -45,15 +46,11 @@ describe('NoTypePolicyInstanceDialogComponent', () => { let loader: HarnessLoader; let policyServiceSpy: jasmine.SpyObj; let errDialogServiceSpy: jasmine.SpyObj; - const ric1: Ric = { ric_id: 'ric1', managed_element_ids: [ 'me1' ], policytype_ids: [ 'type1' ], state: ''}; - const ric2: Ric = { ric_id: 'ric2', managed_element_ids: [ 'me1' ], policytype_ids: [ 'type1' ], state: ''}; beforeEach(async () => { - policyServiceSpy = jasmine.createSpyObj('PolicyService', [ 'putPolicy', 'getRics' ]); + policyServiceSpy = jasmine.createSpyObj('PolicyService', [ 'putPolicy' ]); errDialogServiceSpy = jasmine.createSpyObj('ErrorDialogService', [ 'displayError' ]); - policyServiceSpy.getRics.and.returnValue(of({ rics: [ ric1, ric2 ] })); - TestBed.configureTestingModule({ imports: [ BrowserAnimationsModule, @@ -93,34 +90,25 @@ describe('NoTypePolicyInstanceDialogComponent', () => { expect(ele).toBeFalsy(); }); - it('should contain enabled Target selection with no ric selected and json should be empty', async () => { - let ricSelector: MatSelectHarness = await loader.getHarness(MatSelectHarness.with({selector: '#ricSelector'})); - - expect(await ricSelector.isEmpty()).toBeTruthy(); - expect(await ricSelector.isDisabled()).toBeFalsy(); - await ricSelector.open(); - const count = (await ricSelector.getOptions()).length; - expect(count).toEqual(2); + it('should contain ric select', async () => { + const ele = fixture.debugElement.nativeElement.querySelector('nrcp-ric-selector'); + expect(ele).toBeTruthy(); + }); - let jsonTextArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({selector: '#policyJsonTextArea'})); - expect(await jsonTextArea.isDisabled()).toBeFalsy(); - const actualJson: string = await jsonTextArea.getValue(); - expect(actualJson).toEqual(''); + it('should contain json editor', async () => { + const ele = fixture.debugElement.nativeElement.querySelector('nrcp-no-type-policy-editor'); + expect(ele).toBeTruthy(); }); - it('should contain disabled Format and Submit buttons and enabled Close button', async () => { + it('should contain enabled Close button and disabled Submit button', async () => { component.ngOnInit(); - let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#formatButton'})); - expect(await formatButton.isDisabled()).toBeTruthy(); - expect(await formatButton.getText()).toEqual('Format JSON'); - - 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'})); - expect(await submitButton.isDisabled()).toBeTruthy(); + // expect(await submitButton.isDisabled()).toBeTruthy(); expect(await submitButton.getText()).toEqual('Submit'); }); }); @@ -150,21 +138,17 @@ describe('NoTypePolicyInstanceDialogComponent', () => { expect(ele.innerText).toEqual('[ric1] Instance ID: instanceId'); }); - it('should contain json and no Target selection', async () => { - let ele = fixture.debugElement.nativeElement.querySelector('#ricSelector'); - expect(ele).toBeFalsy(); - - let jsonTextArea: MatInputHarness = await loader.getHarness(MatInputHarness.with({selector: '#policyJsonTextArea'})); - expect(await jsonTextArea.isDisabled()).toBeFalsy(); - const actualJson: string = await jsonTextArea.getValue(); - expect(actualJson).toContain('qosObjectives'); + it('should not contain ric select', async () => { + const ele = fixture.debugElement.nativeElement.querySelector('nrcp-ric-selector'); + expect(ele).toBeFalsy(); }); - it('should contain enabled Format, Submit and Close buttons', async () => { - let formatButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#formatButton'})); - expect(await formatButton.isDisabled()).toBeFalsy(); - expect(await formatButton.getText()).toEqual('Format JSON'); + it('should contain json editor', async () => { + const ele = fixture.debugElement.nativeElement.querySelector('nrcp-no-type-policy-editor'); + expect(ele).toBeTruthy(); + }); + it('should contain enabled Close and Submit buttons', async () => { let closeButton: MatButtonHarness = await loader.getHarness(MatButtonHarness.with({selector: '#closeButton'})); expect(await closeButton.isDisabled()).toBeFalsy(); expect(await closeButton.getText()).toEqual('Close'); 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 index 9dd0d53..ef6bfd0 100644 --- 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 @@ -17,8 +17,8 @@ * limitations under the License. * ========================LICENSE_END=================================== */ -import { Component, Inject, OnInit } from '@angular/core'; -import { FormControl, FormGroup, Validators, ValidatorFn, AbstractControl } from '@angular/forms'; +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'; @@ -26,8 +26,9 @@ 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 { Rics } from '../../interfaces/ric'; 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', @@ -36,7 +37,10 @@ import { CreatePolicyInstance } from '../../interfaces/policy.types'; }) 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; @@ -51,7 +55,7 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { @Inject(MAT_DIALOG_DATA) private data, private ui: UiService) { this.policyInstanceId = data.instanceId; - this.policyJson = data.instanceJson ? this.formatJsonString(data.instanceJson) : ''; + this.policyJson = data.instanceJson ? formatJsonString(data.instanceJson) : '{}'; this.ric = data.ric; } @@ -59,30 +63,15 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { this.ui.darkModeState.subscribe((isDark) => { this.darkMode = isDark; }); - this.instanceForm = new FormGroup({ - 'ricSelector': new FormControl(this.ric, [ - Validators.required - ]), - 'policyJsonTextArea': new FormControl(this.policyJson, [ - Validators.required, - jsonValidator() - ]) - }); - if (!this.policyInstanceId) { - this.getRicIds(); - } + this.instanceForm = new FormGroup({}); } - get policyJsonTextArea() { return this.instanceForm.get('policyJsonTextArea'); } - - get ricSelector() { return this.instanceForm.get('ricSelector'); } - onSubmit() { if (this.policyInstanceId == null) { this.policyInstanceId = uuid.v4(); } const self: NoTypePolicyInstanceDialogComponent = this; - let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(this.policyJsonTextArea.value); + let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(this.policyEditorComponent.policyJsonTextArea.value); this.policySvc.putPolicy(createPolicyInstance).subscribe( { next(_) { @@ -101,48 +90,8 @@ export class NoTypePolicyInstanceDialogComponent implements OnInit { createPolicyInstance.policy_data = JSON.parse(policyJson); createPolicyInstance.policy_id = this.policyInstanceId; createPolicyInstance.policytype_id = ''; - createPolicyInstance.ric_id = (!this.ricSelector.value.ric_id) ? this.ric : this.ricSelector.value.ric_id; + createPolicyInstance.ric_id = this.ricSelectorComponent.selectedRic; createPolicyInstance.service_id = 'controlpanel'; return createPolicyInstance; } - - getRicIds() { - const self: NoTypePolicyInstanceDialogComponent = this; - this.policySvc.getRics('').subscribe( - { - next(value: Rics) { - value.rics.forEach(ric => { - self.allRicIds.push(ric.ric_id); - }); - } - }); - } - - private formatJsonString(jsonToFormat: any): string { - return JSON.stringify(jsonToFormat, null, 2); - } - - formatJsonInput() { - this.policyJson = this.formatJsonString(JSON.parse(this.policyJsonTextArea.value)); - } -} - -export function jsonValidator(): ValidatorFn { - return (control: AbstractControl): { [key: string]: any } | null => { - const notValid = !isJsonValid(control.value); - return notValid ? { 'invalidJson': { value: control.value } } : null; - }; -} - -export function isJsonValid(json: string): boolean { - try { - if (json != null) { - JSON.parse(json); - return true; - } else { - return false; - } - } catch (jsonError) { - return false; - } } diff --git a/webapp-frontend/src/app/policy/policy.module.ts b/webapp-frontend/src/app/policy/policy.module.ts index f7a41dc..9bf2959 100644 --- a/webapp-frontend/src/app/policy/policy.module.ts +++ b/webapp-frontend/src/app/policy/policy.module.ts @@ -31,6 +31,8 @@ import { MatToolbarModule } from '@angular/material/toolbar'; 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'; const routes:Routes = [ {path: 'policy', component: PolicyControlComponent} @@ -43,6 +45,8 @@ const routes:Routes = [ PolicyControlComponent, PolicyInstanceComponent, PolicyInstanceDialogComponent, + RicSelectorComponent, + NoTypePolicyEditorComponent, ], imports: [ CommonModule, @@ -77,6 +81,6 @@ const routes:Routes = [ exports: [ PolicyCardComponent, PolicyControlComponent - ], + ] }) export class PolicyModule { } diff --git a/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.html b/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.html new file mode 100644 index 0000000..1299058 --- /dev/null +++ b/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.html @@ -0,0 +1,16 @@ + + + + {{ric}} + + +
+
+ + This field is required. + +
+
+
\ No newline at end of file diff --git a/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.scss b/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.spec.ts b/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.spec.ts new file mode 100644 index 0000000..0306ec4 --- /dev/null +++ b/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.spec.ts @@ -0,0 +1,94 @@ +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { Component, ViewChild } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { MatSelectModule } from '@angular/material/select'; +import { MatSelectHarness } from '@angular/material/select/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { of } from "rxjs/observable/of"; +import { Ric } from 'src/app/interfaces/ric'; +import { PolicyService } from 'src/app/services/policy/policy.service'; + +import { RicSelectorComponent } from './ric-selector.component'; + +let formGroup: FormGroup = new FormGroup({}); + +describe('RicSelectorComponent', () => { + let component: TestRicSelectorHostComponent; + let fixture: ComponentFixture; + let loader: HarnessLoader; + let policyServiceSpy: jasmine.SpyObj; + const ric1: Ric = { ric_id: 'ric1', managed_element_ids: ['me1'], policytype_ids: ['type1'], state: '' }; + const ric2: Ric = { ric_id: 'ric2', managed_element_ids: ['me1'], policytype_ids: ['type1'], state: '' }; + + beforeEach(async(() => { + policyServiceSpy = jasmine.createSpyObj('PolicyService', ['getRics']); + const policyData = { + createSchema: "{}", + instanceId: null, + instanceJson: '{"qosObjectives": {"priorityLevel": 3100}}', + name: "name", + ric: null + }; + + policyServiceSpy.getRics.and.returnValue(of({ rics: [ric1, ric2] })); + TestBed.configureTestingModule({ + imports: [ + BrowserAnimationsModule, + MatSelectModule, + ], + declarations: [ + RicSelectorComponent, + TestRicSelectorHostComponent + ], + providers: [ + { provide: PolicyService, useValue: policyServiceSpy }, + FormBuilder + ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TestRicSelectorHostComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + loader = TestbedHarnessEnvironment.loader(fixture); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should be added to form group with required validator', async () => { + let ricSelector: MatSelectHarness = await loader.getHarness(MatSelectHarness.with({ selector: '#ricSelector' })); + + expect(formGroup.get('ricSelector')).toBeTruthy(); + expect(await ricSelector.isRequired()).toBeTruthy(); + }); + + it('no ric selected', async () => { + let ricSelector: MatSelectHarness = await loader.getHarness(MatSelectHarness.with({ selector: '#ricSelector' })); + + expect(await ricSelector.isEmpty()).toBeTruthy(); + }); + + it('options should contain rics for policy type', async () => { + let ricSelector: MatSelectHarness = await loader.getHarness(MatSelectHarness.with({ selector: '#ricSelector' })); + + expect(policyServiceSpy.getRics).toHaveBeenCalledWith('policyTypeName'); + await ricSelector.open(); + const count = (await ricSelector.getOptions()).length; + expect(count).toEqual(2); + }); +}); + +@Component({ + selector: `ric-selector-host-component`, + template: `` +}) +export class TestRicSelectorHostComponent { + @ViewChild(RicSelectorComponent) + private ricSelectorComponent: RicSelectorComponent; + instanceForm: FormGroup = formGroup; + policyTypeName: string = 'policyTypeName'; +} diff --git a/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.ts b/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.ts new file mode 100644 index 0000000..583f02a --- /dev/null +++ b/webapp-frontend/src/app/policy/ric-selector/ric-selector.component.ts @@ -0,0 +1,54 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { AbstractControl, ControlContainer, FormBuilder, FormControl, FormGroup, FormGroupDirective, Validators } from '@angular/forms'; +import { Ric, Rics } from 'src/app/interfaces/ric'; +import { PolicyService } from 'src/app/services/policy/policy.service'; + +@Component({ + selector: 'nrcp-ric-selector', + templateUrl: './ric-selector.component.html', + styleUrls: ['./ric-selector.component.scss'], + viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }] + +}) +export class RicSelectorComponent implements OnInit { + + @Input() instanceForm: FormGroup; + @Input() policyTypeName: string = ''; + ric: string; + allRics: string[] = []; + + constructor( + private dataService: PolicyService, + private formBuilder: FormBuilder) { + } + + ngOnInit(): void { + this.instanceForm.addControl( + 'ricSelector', new FormControl(this.ric, [ + Validators.required + ])); + + console.log('Ric:', this.ric); + this.fetchRics(); + } + + get selectedRic(): string { return this.ric; } + + get ricSelector(): AbstractControl { + return this.instanceForm.get('ricSelector'); + } + + private fetchRics() { + console.log('fetchRics ', this.policyTypeName); + const self: RicSelectorComponent = this; + this.dataService.getRics(this.policyTypeName).subscribe( + { + next(value: Rics) { + value.rics.forEach(ric => { + self.allRics.push(ric.ric_id) + }); + console.log(value); + } + }); + } +}