Non-RT RIC Dashboard
[nonrtric.git] / dashboard / webapp-frontend / src / app / policy-control / 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 { Component, OnInit, ViewChild, Inject, AfterViewInit, Self } from '@angular/core';
21 import { MatMenuTrigger } from '@angular/material/menu';
22 import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
23 import { trigger, state, style, animate, transition } from '@angular/animations';
24 import * as uuid from 'uuid';
25
26 import { JsonPointer } from 'angular6-json-schema-form';
27 import { PolicyService } from '../services/policy/policy.service';
28 import { ErrorDialogService } from '../services/ui/error-dialog.service';
29 import { NotificationService } from './../services/ui/notification.service';
30
31 import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
32 import { PolicyType } from '../interfaces/policy.types';
33 import { PolicyInstance } from '../interfaces/policy.types';
34
35 @Component({
36     selector: 'rd-policy-instance-dialog',
37     templateUrl: './policy-instance-dialog.component.html',
38     styleUrls: ['./policy-instance-dialog.component.scss'],
39     animations: [
40         trigger('expandSection', [
41             state('in', style({ height: '*' })),
42             transition(':enter', [
43                 style({ height: 0 }), animate(100),
44             ]),
45             transition(':leave', [
46                 style({ height: '*' }),
47                 animate(100, style({ height: 0 })),
48             ]),
49         ]),
50     ],
51 })
52 export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit {
53
54     formActive = false;
55     isVisible = {
56         form: true,
57         json: false,
58         schema: false
59     };
60
61     jsonFormStatusMessage = 'Loading form...';
62     jsonSchemaObject: any = {};
63     jsonObject: any = {};
64
65
66     jsonFormOptions: any = {
67         addSubmit: false, // Add a submit button if layout does not have one
68         debug: false, // Don't show inline debugging information
69         loadExternalAssets: true, // Load external css and JavaScript for frameworks
70         returnEmptyFields: false, // Don't return values for empty input fields
71         setSchemaDefaults: true, // Always use schema defaults for empty fields
72         defautWidgetOptions: { feedback: true }, // Show inline feedback icons
73     };
74
75     liveFormData: any = {};
76     formValidationErrors: any;
77     formIsValid = false;
78
79
80     @ViewChild(MatMenuTrigger, { static: true }) menuTrigger: MatMenuTrigger;
81
82     public policyInstanceId: string;
83     public policyTypeName: string;
84     private policyTypeId: number;
85
86     constructor(
87         private dataService: PolicyService,
88         private errorService: ErrorDialogService,
89         private notificationService: NotificationService,
90         @Inject(MAT_DIALOG_DATA) private data,
91         private dialogRef: MatDialogRef<PolicyInstanceDialogComponent>) {
92         this.formActive = false;
93         this.policyInstanceId = this.data.instanceId;
94         this.policyTypeName = this.data.name;
95         this.policyTypeId = this.data.policyTypeId;
96         this.parseJson(data.createSchema, data.instanceJson);
97     }
98
99     ngOnInit() {
100         this.jsonFormStatusMessage = 'Init';
101         this.formActive = true;
102     }
103
104     ngAfterViewInit() {
105     }
106
107     onSubmit() {
108         if (this.policyInstanceId == null) {
109             this.policyInstanceId = uuid.v4();
110         }
111         const policyJson: string = this.prettyLiveFormData;
112         const self: PolicyInstanceDialogComponent = this;
113         this.dataService.putPolicy(this.policyTypeId, this.policyInstanceId, policyJson).subscribe(
114             {
115                 next(value) {
116                     self.notificationService.success('Policy ' + self.policyTypeName + ':' + self.policyInstanceId + ' submitted');
117                 },
118                 error(error) {
119                     self.errorService.displayError('updatePolicy failed: ' + error.message);
120                 },
121                 complete() { }
122             });
123     }
124
125     onClose() {
126         this.dialogRef.close();
127     }
128
129     public onChanges(data: any) {
130         this.liveFormData = data;
131     }
132
133     get prettyLiveFormData() {
134         return JSON.stringify(this.liveFormData, null, 2);
135     }
136
137     get schemaAsString() {
138         return JSON.stringify(this.jsonSchemaObject, null, 2);
139     }
140
141     get jsonAsString() {
142         return JSON.stringify(this.jsonObject, null, 2);
143     }
144
145     isValid(isValid: boolean): void {
146         this.formIsValid = isValid;
147     }
148
149     validationErrors(data: any): void {
150         this.formValidationErrors = data;
151     }
152
153     get prettyValidationErrors() {
154         if (!this.formValidationErrors) { return null; }
155         const errorArray = [];
156         for (const error of this.formValidationErrors) {
157             const message = error.message;
158             const dataPathArray = JsonPointer.parse(error.dataPath);
159             if (dataPathArray.length) {
160                 let field = dataPathArray[0];
161                 for (let i = 1; i < dataPathArray.length; i++) {
162                     const key = dataPathArray[i];
163                     field += /^\d+$/.test(key) ? `[${key}]` : `.${key}`;
164                 }
165                 errorArray.push(`${field}: ${message}`);
166             } else {
167                 errorArray.push(message);
168             }
169         }
170         return errorArray.join('<br>');
171     }
172
173     private parseJson(createSchema: string, instanceJson: string): void {
174         try {
175             this.jsonSchemaObject = JSON.parse(createSchema);
176             if (this.data.instanceJson != null) {
177                 this.jsonObject = JSON.parse(instanceJson);
178             }
179         } catch (jsonError) {
180             this.jsonFormStatusMessage =
181                 'Invalid JSON\n' +
182                 'parser returned:\n\n' + jsonError;
183             return;
184         }
185     }
186
187     public toggleVisible(item: string) {
188         this.isVisible[item] = !this.isVisible[item];
189     }
190 }
191
192 export function getPolicyDialogProperties(policyType: PolicyType, instance: PolicyInstance): MatDialogConfig {
193     const policyTypeId = policyType.policy_type_id;
194     const createSchema = policyType.create_schema;
195     const instanceId = instance ? instance.instanceId : null;
196     const instanceJson = instance ? instance.instance : null;
197     const name = policyType.name;
198
199     return {
200         maxWidth: '1200px',
201         height: '1200px',
202         width: '900px',
203         role: 'dialog',
204         disableClose: false,
205         data: {
206             policyTypeId,
207             createSchema,
208             instanceId,
209             instanceJson,
210             name
211         }
212     };
213 }
214