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