package org.oransc.portal.nonrtric.controlpanel.config;
import com.google.gson.GsonBuilder;
-
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Optional;
import java.util.Vector;
import java.util.stream.Collectors;
-
import org.oransc.portal.nonrtric.controlpanel.model.ImmutablePolicyInfo;
import org.oransc.portal.nonrtric.controlpanel.model.PolicyInfo;
import org.oransc.portal.nonrtric.controlpanel.model.PolicyInstances;
class Database {
Database() {
+ PolicyType policyType = new PolicyType("", "{}");
+ types.put("", policyType);
+
String schema = getStringFromFile("demo-policy-schema-1.json");
- PolicyType policyType = new PolicyType("type2", schema);
+ policyType = new PolicyType("type2", schema);
types.put("type2", policyType);
schema = getStringFromFile("demo-policy-schema-2.json");
schema = getStringFromFile("demo-policy-schema-3.json");
policyType = new PolicyType("type4", schema);
types.put("type4", policyType);
+
+ putInstance("", "123", "{\"data\":\"data\"}", "ric_1");
}
private String getStringFromFile(String path) {
import { FooterComponent } from './footer/footer.component';
import { MainComponent } from './main/main.component';
import { MaterialDesignFrameworkModule } from 'angular6-json-schema-form';
+import { NoTypePolicyInstanceDialogComponent } from './policy-control/no-type-policy-instance-dialog.component';
import { PolicyCardComponent } from './ui/policy-card/policy-card.component';
import { PolicyControlComponent } from './policy-control/policy-control.component';
import { PolicyInstanceComponent } from './policy-control/policy-instance.component';
ErrorDialogComponent,
FooterComponent,
MainComponent,
+ NoTypePolicyInstanceDialogComponent,
PolicyCardComponent,
PolicyControlComponent,
PolicyInstanceComponent,
entryComponents: [
ConfirmDialogComponent,
ErrorDialogComponent,
+ NoTypePolicyInstanceDialogComponent,
PolicyInstanceDialogComponent
],
providers: [
--- /dev/null
+<!--
+ ========================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="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>Policy with no type</tspan>
+ </text>
+ </svg>
+ </div>
+</div>
+
+<div class="text-muted">Since this is a policy type without a schema, the user will have to make sure that the content
+ of the policy has the necessary content. This dialog will only validate that it is a valid JSON string.</div>
+
+<form [formGroup]="instanceForm" novalidate autocomplete="off">
+ <div mat-dialog-content>
+ <mat-form-field *ngIf="!this.policyInstanceId">
+ <mat-label [class.text-danger]="!this.ric">Select RIC</mat-label>
+ <mat-select id="ricSelector" formControlName="ricSelector" matInput required [(value)]="this.ric">
+ <mat-option *ngFor="let ric of this.allRics" [value]="ric">
+ {{ric}}
+ </mat-option>
+ </mat-select>
+ <div *ngIf="ricSelector.invalid && (ricSelector.dirty || ricSelector.touched)"
+ class="alert alert-danger">
+ <div *ngIf="ricSelector.errors.required">
+ A Ric must be selected.
+ </div>
+ </div>
+ </mat-form-field>
+
+ <mat-form-field style="width: 800px;">
+ <mat-label>Policy content</mat-label>
+ <textarea id="policyJsonTextArea" formControlName="policyJsonTextArea" matInput cdkTextareaAutosize
+ cdkAutosizeMinRows="10" required>
+ </textarea>
+ <div *ngIf="policyJsonTextArea.invalid && (policyJsonTextArea.dirty || policyJsonTextArea.touched)"
+ class="alert alert-danger">
+ <div *ngIf="policyJsonTextArea.errors.required">
+ The policy body is required.
+ </div>
+ <div *ngIf="policyJsonTextArea.errors.invalidJson">
+ The policy body must be a valid JSON.
+ </div>
+ </div>
+ </mat-form-field>
+ </div>
+ <div mat-dialog-actions class="modal-footer justify-content-center">
+ <button mat-raised-button (click)="this.onSubmit()" class="submitBtn" [disabled]="!instanceForm.valid">
+ Submit
+ </button>
+ <button mat-raised-button class="mat-raised-button" [mat-dialog-close]="false">Close</button>
+ </div>
+</form>
\ No newline at end of file
--- /dev/null
+/*-
+ * ========================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;
+}
--- /dev/null
+/*-
+ * ========================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 } from '@angular/core';
+import { FormControl, FormGroup, Validators, ValidatorFn, AbstractControl } from '@angular/forms';
+import { 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';
+
+@Component({
+ selector: 'rd-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 {
+
+ // Declare following variables as Public variable. Private variables should not be used in template HTML
+ instanceForm: FormGroup;
+
+ policyInstanceId: string; // null if not yet created
+ policyJson: string;
+ darkMode: boolean;
+ ric: string;
+ allRics: string[];
+
+ constructor(
+ 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 ? JSON.stringify(JSON.parse(data.instanceJson), null, 2) : '';
+ this.ric = data.ric;
+ }
+
+ ngOnInit() {
+ 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.fetchRics();
+ }
+ }
+
+ 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;
+ this.policySvc.putPolicy('', this.policyInstanceId, this.policyJsonTextArea.value, this.ric).subscribe(
+ {
+ next(_) {
+ self.notificationService.success('Policy without type:' + self.policyInstanceId + ' submitted');
+ },
+ error(error: HttpErrorResponse) {
+ self.errorService.displayError('Submit failed: ' + error.error);
+ },
+ complete() { }
+ });
+ }
+
+ private fetchRics() {
+ const self: NoTypePolicyInstanceDialogComponent = this;
+ this.policySvc.getRics('').subscribe(
+ {
+ next(value) {
+ self.allRics = value;
+ console.log(value);
+ },
+ error(error: HttpErrorResponse) {
+ self.errorService.displayError('Fetching of rics failed: ' + error.message);
+ },
+ complete() { }
+ });
+ }
+}
+
+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) {
+ try {
+ if (json != null) {
+ JSON.parse(json);
+ return true;
+ }
+ } catch (jsonError) {
+ return false;
+ }
+}
<ng-container matColumnDef="action">
<mat-header-cell class="action-cell" *matHeaderCellDef>Action </mat-header-cell>
<mat-cell class="action-cell" *matCellDef="let policyType" (click)="$event.stopPropagation()">
- <button [disabled]="this.isSchemaEmpty(policyType)" mat-icon-button
- (click)="createPolicyInstance(policyType)">
+ <button mat-icon-button (click)="createPolicyInstance(policyType)">
<mat-icon matTooltip="Create instance">add_box</mat-icon>
</button>
</mat-cell>
import { NotificationService } from '../services/ui/notification.service';
import { BehaviorSubject, Observable } from 'rxjs';
import { UiService } from '../services/ui/ui.service';
+import { NoTypePolicyInstanceDialogComponent } from './no-type-policy-instance-dialog.component';
class PolicyTypeInfo {
constructor(public type: PolicyType) { }
}
createPolicyInstance(policyType: PolicyType): void {
- const dialogRef = this.dialog.open(PolicyInstanceDialogComponent, getPolicyDialogProperties(policyType, null, this.darkMode));
+ let dialogRef;
+ if (this.isSchemaEmpty(policyType)) {
+ dialogRef = this.dialog.open(NoTypePolicyInstanceDialogComponent,
+ getPolicyDialogProperties(policyType, null, this.darkMode));
+ } else {
+ dialogRef = this.dialog.open(PolicyInstanceDialogComponent,
+ getPolicyDialogProperties(policyType, null, this.darkMode));
+ }
const info: PolicyTypeInfo = this.getPolicyTypeInfo(policyType);
dialogRef.afterClosed().subscribe(
- (result: any) => {
+ (_) => {
info.isExpanded.next(info.isExpanded.getValue());
}
);
[class.text-danger]="!formIsValid">
{{formIsValid ? 'Json' : 'Not valid'}}
</strong>
- <strong class="text-danger" *ngIf="!formIsValid && !prettyValidationErrors">Not submittable</strong>
+ <span *ngIf="!formIsValid && !prettyValidationErrors">Invalid form</span>
<span *ngIf="prettyValidationErrors">— errors:</span>
<div *ngIf="prettyValidationErrors" class="text-danger" [innerHTML]="prettyValidationErrors"></div>
</div>
if (!this.policyInstanceId) {
this.fetchRics();
}
- if (this.isSchemaEmpty()) {
- // Empty schema, hide form, show json instead
- this.isVisible.form = false;
- this.isVisible.json = true;
- }
}
ngAfterViewInit() {
}
- private isSchemaEmpty(): boolean {
- return Object.keys(this.jsonSchemaObject).length === 0;
- }
-
onSubmit() {
if (this.policyInstanceId == null) {
this.policyInstanceId = uuid.v4();
const self: PolicyInstanceDialogComponent = this;
this.dataService.putPolicy(this.policyTypeName, this.policyInstanceId, policyJson, this.ric).subscribe(
{
- next(value) {
- self.notificationService.success('Policy ' + self.policyTypeName + ':' + self.policyInstanceId + ' submitted');
+ next(_) {
+ self.notificationService.success('Policy ' + self.policyTypeName + ':' + self.policyInstanceId +
+ ' submitted');
},
error(error: HttpErrorResponse) {
self.errorService.displayError('Submit failed: ' + error.error);
this.liveFormData = formData;
}
- get prettyLiveFormData(): string {
- if (this.isSchemaEmpty()) {
- return this.jsonAsString;
- }
+ get prettyLiveFormData() {
return JSON.stringify(this.liveFormData, null, 2);
}
- get schemaAsString(): string {
+ get schemaAsString() {
return JSON.stringify(this.jsonSchemaObject, null, 2);
}
- get jsonAsString(): string {
+ get jsonAsString() {
return JSON.stringify(this.jsonObject, null, 2);
}
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.component';
import { PolicyInstanceDialogComponent } from './policy-instance-dialog.component';
import { getPolicyDialogProperties } from './policy-instance-dialog.component';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
}
}
+ private isSchemaEmpty(): boolean {
+ return Object.keys(this.policyType.schemaObject).length === 0;
+ }
+
modifyInstance(instance: PolicyInstance): void {
this.policySvc.getPolicy(this.policyType.name, instance.id).subscribe(
(refreshedJson: any) => {
instance.json = JSON.stringify(refreshedJson);
- this.dialog.open(PolicyInstanceDialogComponent, getPolicyDialogProperties(this.policyType, instance, this.darkMode));
+ if (this.isSchemaEmpty()) {
+ this.dialog.open(
+ NoTypePolicyInstanceDialogComponent,
+ getPolicyDialogProperties(this.policyType, instance, this.darkMode));
+ } else {
+ this.dialog.open(
+ PolicyInstanceDialogComponent,
+ getPolicyDialogProperties(this.policyType, instance, this.darkMode));
+ }
},
(httpError: HttpErrorResponse) => {
- this.notificationService.error('Could not refresh instance ' + httpError.message);
- this.dialog.open(PolicyInstanceDialogComponent, getPolicyDialogProperties(this.policyType, instance, this.darkMode));
+ this.notificationService.error('Could not refresh instance. Please try again.' + httpError.message);
}
);
}