Clean up and add license headings
[portal/nonrtric-controlpanel.git] / webapp-frontend / src / app / policy / policy-instance-dialog / policy-instance-dialog.component.ts
1 /*-
2  * ========================LICENSE_START=================================
3  * O-RAN-SC
4  * %%
5  * Copyright (C) 2019 Nordix Foundation
6  * %%
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ========================LICENSE_END===================================
19  */
20 import { animate, state, style, transition, trigger } from '@angular/animations';
21 import { AfterViewInit, Component, Inject, OnInit, ViewChild } from '@angular/core';
22 import { MatDialogConfig, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
23 import { JsonPointer } from 'angular6-json-schema-form';
24 import * as uuid from 'uuid';
25 import { CreatePolicyInstance, PolicyInstance, PolicyTypeSchema } from '../../interfaces/policy.types';
26 import { PolicyService } from '../../services/policy/policy.service';
27 import { ErrorDialogService } from '../../services/ui/error-dialog.service';
28 import { NotificationService } from './../../services/ui/notification.service';
29 import { UiService } from '../../services/ui/ui.service';
30 import { HttpErrorResponse } from '@angular/common/http';
31 import { FormGroup, FormControl, Validators } from '@angular/forms';
32 import { ChangeDetectorRef } from '@angular/core';
33 import { Ric, Rics } from '../../interfaces/ric';
34
35
36 @Component({
37     selector: 'nrcp-policy-instance-dialog',
38     templateUrl: './policy-instance-dialog.component.html',
39     styleUrls: ['./policy-instance-dialog.component.scss'],
40     animations: [
41         trigger('expandSection', [
42             state('in', style({ height: '*' })),
43             transition(':enter', [
44                 style({ height: 0 }), animate(100),
45             ]),
46             transition(':leave', [
47                 style({ height: '*' }),
48                 animate(100, style({ height: 0 })),
49             ]),
50         ]),
51     ],
52 })
53 export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit {
54     instanceForm: FormGroup;
55
56
57     formActive = false;
58     isVisible = {
59         form: true,
60         json: false,
61         schema: false
62     };
63
64     jsonFormStatusMessage = 'Loading form...';
65     jsonSchemaObject: any = {};
66     jsonObject: any = {};
67
68
69     jsonFormOptions: any = {
70         addSubmit: false, // Add a submit button if layout does not have one
71         debug: false, // Don't show inline debugging information
72         loadExternalAssets: true, // Load external css and JavaScript for frameworks
73         returnEmptyFields: false, // Don't return values for empty input fields
74         setSchemaDefaults: true, // Always use schema defaults for empty fields
75         defautWidgetOptions: { feedback: true }, // Show inline feedback icons
76     };
77
78     liveFormData: any = {};
79     formValidationErrors: any;
80     formIsValid = false;
81
82     policyInstanceId: string; // null if not yet created
83     policyTypeName: string;
84     darkMode: boolean;
85     ric: string;
86     allRics: Ric[];
87
88     private fetchRics() {
89         console.log('fetchRics ' + this.policyTypeName);
90         const self: PolicyInstanceDialogComponent = this;
91         this.dataService.getRics(this.policyTypeName).subscribe(
92             {
93                 next(value: Rics) {
94                     self.allRics = value.rics;
95                     console.log(value);
96                 }
97             });
98     }
99
100     constructor(
101         private cdr: ChangeDetectorRef,
102         private dataService: PolicyService,
103         private errorService: ErrorDialogService,
104         private notificationService: NotificationService,
105         @Inject(MAT_DIALOG_DATA) private data,
106         private dialogRef: MatDialogRef<PolicyInstanceDialogComponent>,
107         private ui: UiService) {
108         this.formActive = false;
109         this.policyInstanceId = data.instanceId;
110         this.policyTypeName = data.name;
111         this.jsonSchemaObject = data.createSchema;
112         this.jsonObject = data.instanceJson;
113         this.ric = data.ric;
114     }
115
116     ngOnInit() {
117         this.jsonFormStatusMessage = 'Init';
118         this.formActive = true;
119         this.ui.darkModeState.subscribe((isDark) => {
120             this.darkMode = isDark;
121         });
122         this.instanceForm = new FormGroup({
123             'ricSelector': new FormControl(this.ric, [
124                 Validators.required
125             ])
126         });
127         if (!this.policyInstanceId) {
128             this.fetchRics();
129         }
130     }
131
132     ngAfterViewInit() {
133         this.cdr.detectChanges();
134     }
135
136     get ricSelector() { return this.instanceForm.get('ricSelector'); }
137
138     onSubmit() {
139         if (this.policyInstanceId == null) {
140             this.policyInstanceId = uuid.v4();
141         }
142         const policyJson: string = this.prettyLiveFormData;
143         const self: PolicyInstanceDialogComponent = this;
144         let createPolicyInstance: CreatePolicyInstance = this.createPolicyInstance(policyJson);
145         this.dataService.putPolicy(createPolicyInstance).subscribe(
146             {
147                 next(_) {
148                     self.notificationService.success('Policy ' + self.policyTypeName + ':' + self.policyInstanceId +
149                         ' submitted');
150                     self.dialogRef.close();
151                 },
152                 error(error: HttpErrorResponse) {
153                     self.errorService.displayError('Submit failed: ' + error.error);
154                 },
155                 complete() { }
156             });
157     }
158
159     private createPolicyInstance(policyJson: string) {
160         let createPolicyInstance = {} as CreatePolicyInstance;
161         createPolicyInstance.policy_data = JSON.parse(policyJson);
162         createPolicyInstance.policy_id = this.policyInstanceId;
163         createPolicyInstance.policytype_id = this.policyTypeName;
164         createPolicyInstance.ric_id = (!this.ricSelector.value.ric_id) ? this.ric : this.ricSelector.value.ric_id;
165         createPolicyInstance.service_id = 'controlpanel';
166         return createPolicyInstance;
167     }
168
169     onClose() {
170         this.dialogRef.close();
171     }
172
173     public onChanges(formData: any) {
174         this.liveFormData = formData;
175     }
176
177     get prettyLiveFormData(): string {
178         return JSON.stringify(this.liveFormData, null, 2);
179     }
180
181     get schemaAsString(): string {
182         return JSON.stringify(this.jsonSchemaObject, null, 2);
183     }
184
185     get jsonAsString(): string {
186         return JSON.stringify(this.jsonObject, null, 2);
187     }
188
189     isValid(isValid: boolean): void {
190         this.formIsValid = isValid;
191     }
192
193     validationErrors(validationErrors: any): void {
194         this.formValidationErrors = validationErrors;
195     }
196
197     get prettyValidationErrors() {
198         if (!this.formValidationErrors) { return null; }
199         const errorArray = [];
200         for (const error of this.formValidationErrors) {
201             const message = error.message;
202             const dataPathArray = JsonPointer.parse(error.dataPath);
203             if (dataPathArray.length) {
204                 let field = dataPathArray[0];
205                 for (let i = 1; i < dataPathArray.length; i++) {
206                     const key = dataPathArray[i];
207                     field += /^\d+$/.test(key) ? `[${key}]` : `.${key}`;
208                 }
209                 errorArray.push(`${field}: ${message}`);
210             } else {
211                 errorArray.push(message);
212             }
213         }
214         return errorArray.join('<br>');
215     }
216
217     private parseJson(str: string): string {
218         try {
219             if (str != null) {
220                 return JSON.parse(str);
221             }
222         } catch (jsonError) {
223             this.jsonFormStatusMessage =
224                 'Invalid JSON\n' +
225                 'parser returned:\n\n' + jsonError;
226         }
227         return null;
228     }
229
230     public toggleVisible(item: string) {
231         this.isVisible[item] = !this.isVisible[item];
232     }
233 }
234
235 export function getPolicyDialogProperties(policyTypeSchema: PolicyTypeSchema, instance: PolicyInstance, darkMode: boolean): MatDialogConfig {
236     const createSchema = policyTypeSchema.schemaObject;
237     const instanceId = instance ? instance.policy_id : null;
238     const instanceJson = instance ? instance.policy_data : null;
239     const name = policyTypeSchema.name;
240     const ric = instance ? instance.ric_id : null;
241     return {
242         maxWidth: '1200px',
243         maxHeight: '900px',
244         width: '900px',
245         role: 'dialog',
246         disableClose: false,
247         panelClass: darkMode ? 'dark-theme' : '',
248         data: {
249             createSchema,
250             instanceId,
251             instanceJson,
252             name,
253             ric
254         }
255     };
256 }
257