-->
<div mat-dialog-title *ngIf="loading$ | async">
- Loading {{data.xapp.name}} Configuration
+ Loading {{data.xapp}} Configuration
<mat-spinner diameter=70></mat-spinner>
</div>
<div *ngIf="((loading$ | async)==false) " class="config-div">
<div mat-dialog-title class="config-title">
- {{data.xapp.name}} Configuration
+ {{data.xapp}} Configuration
</div>
- <div class="config-form">
- <json-schema-form loadExternalAssets="true"
- framework="material-design"
- [data]="xappConfigData"
- [schema]="xappConfigSchema"
- [layout]="xappLayout"
- (onSubmit)="updateconfig($event)">
- </json-schema-form>
+ <mat-form-field>
+ <textarea #configTextarea matInput class="config-textarea">{{xappConfig | json}}</textarea>
+ </mat-form-field>
+ <div class="modal-footer justify-content-center">
+ <button mat-button class="mat-raised-button mat-primary" (click)="updateconfig(configTextarea.value)" >upload</button>
+ <button mat-button class="mat-raised-button" [mat-dialog-close]="false">Cancel</button>
</div>
</div>
margin-bottom:0px
}
-.config-form {
- max-height: 400px;
- overflow-y:scroll;
+.config-textarea {
+ height: 300px;
+ overflow-y: scroll;
}
-.config-form::-webkit-scrollbar {
+.config-textarea::-webkit-scrollbar {
display: none;
}
.mat-form-field-wrapper{
margin-right:10px
+}
+
+.mat-raised-button {
+ margin-right: 5px;
+}
+
+mat-form-field {
+ width: 90%
}
\ No newline at end of file
import { LoadingDialogService } from '../services/ui/loading-dialog.service';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { NotificationService } from '../services/ui/notification.service';
+import { XMXappConfig } from "../interfaces/app-mgr.types"
@Component({
selector: 'rd-app-configuration',
@Inject(MAT_DIALOG_DATA) private data
) { }
- xappMetadata: any;
- xappConfigSchema: any;
- xappConfigData: any;
- xappLayout: any;
+ xappConfig: XMXappConfig
+
ngOnInit() {
this.loadingSubject.next(true);
this.appMgrService.getConfig(this.data.instanceKey)
)
.subscribe(
(allConfig: any) => {
- this.loadConfigForm(this.data.xapp.name, allConfig);
+ this.loadConfigForm(this.data.xapp, allConfig);
}
);
}
- updateconfig(event) {
- const config = {
- metadata: this.xappMetadata,
- descriptor: this.xappConfigSchema,
- config: event,
- layout: this.xappLayout
- };
- this.loadingDialogService.startLoading('Updating ' + this.data.xapp.name + ' configuration');
- this.appMgrService.putConfig(this.data.instanceKey, config)
+ updateconfig(config: any) {
+ this.loadingDialogService.startLoading('Updating ' + this.data.xapp + ' configuration');
+ this.appMgrService.putConfig(this.data.instanceKey, JSON.parse(config))
.pipe(
finalize(() => {
this.loadingDialogService.stopLoading();
loadConfigForm(name: string, allConfig: any) {
const xappConfig = allConfig.find(xapp => xapp.metadata.name === name);
if (xappConfig != null) {
- this.xappMetadata = xappConfig.metadata;
- this.xappConfigSchema = xappConfig.descriptor;
- this.xappConfigData = xappConfig.config;
- this.xappLayout = xappConfig.layout;
+ this.xappConfig = xappConfig
} else {
this.errorDiaglogService.displayError('Cannot find configration data for ' + name);
this.dialogRef.close();
<mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
<!-- click on button should not expand/collapse the row -->
<mat-cell *matCellDef="let element" (click)="$event.stopPropagation()">
- <button mat-icon-button (click)="controlApp(element)">
+ <button mat-icon-button (click)="onConfigureApp(element)">
<mat-icon matTooltip="Adjust settings">settings</mat-icon>
</button>
+<!-- <button mat-icon-button (click)="controlApp(element)">
+ <mat-icon matTooltip="Adjust settings">settings</mat-icon>
+ </button>-->
<button mat-icon-button (click)="onUndeployApp(element)">
<mat-icon matTooltip="Undeploy app">cloud_download</mat-icon>
</button>
*/
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
import { MatSort } from '@angular/material/sort';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { ErrorDialogService } from '../services/ui/error-dialog.service';
import { LoadingDialogService } from '../services/ui/loading-dialog.service';
import { NotificationService } from '../services/ui/notification.service';
+import { UiService } from '../services/ui/ui.service';
+import { AppConfigurationComponent } from './../app-configuration/app-configuration.component';
import { AppControlAnimations } from './app-control.animations';
import { AppControlDataSource } from './app-control.datasource';
})
export class AppControlComponent implements OnInit, OnDestroy {
+ darkMode: boolean;
+ panelClass: string;
displayedColumns: string[] = ['xapp', 'name', 'status', 'ip', 'port', 'action'];
dataSource: AppControlDataSource;
@ViewChild(MatSort, { static: true }) sort: MatSort;
constructor(
private appMgrSvc: AppMgrService,
private router: Router,
+ private dialog: MatDialog,
private confirmDialogService: ConfirmDialogService,
private errorDialogService: ErrorDialogService,
private loadingDialogService: LoadingDialogService,
public instanceSelectorService: InstanceSelectorService,
- private notificationService: NotificationService) { }
+ private notificationService: NotificationService,
+ public ui: UiService
+ ) { }
ngOnInit() {
this.dataSource = new AppControlDataSource(this.appMgrSvc, this.sort, this.notificationService);
+ this.ui.darkModeState.subscribe((isDark) => {
+ this.darkMode = isDark;
+ });
this.instanceChange = this.instanceSelectorService.getSelectedInstance().subscribe((instance: RicInstance) => {
if (instance.key) {
this.instanceKey = instance.key;
this.errorDialogService.displayError('No control available for ' + app.xapp + ' (yet)');
}
+ onConfigureApp(xappRow: XappControlRow): void {
+ if (this.darkMode) {
+ this.panelClass = 'dark-theme';
+ } else {
+ this.panelClass = '';
+ }
+ const dialogRef = this.dialog.open(AppConfigurationComponent, {
+ panelClass: this.panelClass,
+ width: '80%',
+ maxHeight: '70%',
+ position: {
+ top: '10%'
+ },
+ data: {
+ xapp: xappRow.xapp,
+ instanceKey: this.instanceKey
+ }
+
+ });
+ }
+
onUndeployApp(app: XappControlRow): void {
this.confirmDialogService.openConfirmDialog('Are you sure you want to undeploy App ' + app.xapp + '?')
.afterClosed().subscribe((res: boolean) => {
<mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
<mat-cell *matCellDef="let element">
<div class="catalog-button-row">
- <button mat-icon-button (click)="onConfigureApp(element)">
- <mat-icon matTooltip="Adjust settings">settings</mat-icon>
- </button>
<button mat-icon-button (click)="onDeployApp(element)">
<mat-icon matTooltip="Deploy app">cloud_upload</mat-icon>
</button>
import { NotificationService } from '../services/ui/notification.service';
import { UiService } from '../services/ui/ui.service';
import { DeployDialogComponent } from '../ui/deploy-dialog/deploy-dialog.component';
-import { AppConfigurationComponent } from './../app-configuration/app-configuration.component';
import { OnboardComponent } from './../onboard/onboard.component';
import { CatalogDataSource } from './catalog.datasource';
constructor(
private appMgrService: AppMgrService,
- private confirmDialogService: ConfirmDialogService,
private dialog: MatDialog,
- private loadingDialogService: LoadingDialogService,
private notificationService: NotificationService,
public instanceSelectorService: InstanceSelectorService,
public ui: UiService) { }
this.instanceChange.unsubscribe();
}
- onConfigureApp(xapp: XMXapp): void {
- if (this.darkMode) {
- this.panelClass = 'dark-theme';
- } else {
- this.panelClass = '';
- }
- const dialogRef = this.dialog.open(AppConfigurationComponent, {
- panelClass: this.panelClass,
- width: '40%',
- maxHeight: '500px',
- position: {
- top: '10%'
- },
- data: {
- xapp: xapp,
- instanceKey: this.instanceKey
- }
-
- });
- }
-
onDeployApp(app: XMXapp): void {
if (this.darkMode) {
this.panelClass = 'dark-theme';
getConfig(instanceKey: string): Observable<XMAllXappConfig> {
// For demo purpose, pull example config from local
- return this.httpClient.get<XMAllXappConfig>('/assets/mockdata/config.json');
+ //return this.httpClient.get<XMAllXappConfig>('/assets/mockdata/config.json');
// Once Xapp manager contains layout, should call backend to get xapp config
- // const path = this.dashboardSvc.buildPath(this.component, instanceKey, 'config');
- // return this.httpClient.get<any[]>(path);
+ const path = this.dashboardSvc.buildPath(this.component, instanceKey, 'config');
+ return this.httpClient.get<any[]>(path);
}
putConfig(instanceKey: string, config: XMXappConfig): Observable<HttpResponse<Object>> {
"configName": "UEEC-appconfig",
"namespace": "ricxapp"
},
- "descriptor": {
- "definitions": {},
- "$schema": "http://json-schema.org/draft-07/schema#",
- "$id": "http://example.com/root.json",
- "type": "object",
- "title": "The Root Schema",
- "required": [
- "local",
- "logger",
- "rmr",
- "db",
- "controls",
- "metrics"
- ],
- "properties": {
- "local": {
- "$id": "#/properties/local",
- "type": "object",
- "title": "The Local Schema",
- "required": [
- "host"
- ],
- "properties": {
- "host": {
- "$id": "#/properties/local/properties/host",
- "type": "string",
- "title": "The Host Schema",
- "default": "",
- "examples": [
- ":8080"
- ],
- "pattern": "^(.*)$"
- }
- }
- },
- "logger": {
- "$id": "#/properties/logger",
- "type": "object",
- "title": "The Logger Schema",
- "required": [
- "level"
- ],
- "properties": {
- "level": {
- "$id": "#/properties/logger/properties/level",
- "type": "integer",
- "title": "The Level Schema",
- "default": 0,
- "examples": [
- 3
- ]
- }
- }
- },
- "rmr": {
- "$id": "#/properties/rmr",
- "type": "object",
- "title": "The Rmr Schema",
- "required": [
- "protPort",
- "maxSize",
- "numWorkers",
- "txMessages",
- "rxMessages"
- ],
- "properties": {
- "protPort": {
- "$id": "#/properties/rmr/properties/protPort",
- "type": "string",
- "title": "The Protport Schema",
- "default": "",
- "examples": [
- "tcp:4560"
- ],
- "pattern": "^(.*)$"
- },
- "maxSize": {
- "$id": "#/properties/rmr/properties/maxSize",
- "type": "integer",
- "title": "The Maxsize Schema",
- "default": 0,
- "examples": [
- 2072
- ]
- },
- "numWorkers": {
- "$id": "#/properties/rmr/properties/numWorkers",
- "type": "integer",
- "title": "The Numworkers Schema",
- "default": 0,
- "examples": [
- 1
- ]
- },
- "txMessages": {
- "$id": "#/properties/rmr/properties/txMessages",
- "type": "array",
- "title": "The Txmessages Schema",
- "items": {
- "$id": "#/properties/rmr/properties/txMessages/items",
- "type": "string",
- "title": "The Items Schema",
- "default": "",
- "examples": [
- "RIC_SUB_REQ",
- "RIC_SUB_DEL_REQ"
- ],
- "pattern": "^(.*)$"
- }
- },
- "rxMessages": {
- "$id": "#/properties/rmr/properties/rxMessages",
- "type": "array",
- "title": "The Rxmessages Schema",
- "items": {
- "$id": "#/properties/rmr/properties/rxMessages/items",
- "type": "string",
- "title": "The Items Schema",
- "default": "",
- "examples": [
- "RIC_SUB_RESP",
- "RIC_SUB_FAILURE",
- "RIC_SUB_DEL_RESP",
- "RIC_SUB_DEL_FAILURE",
- "RIC_INDICATION"
- ],
- "pattern": "^(.*)$"
- }
- }
- }
- },
- "db": {
- "$id": "#/properties/db",
- "type": "object",
- "title": "The Db Schema",
- "required": [
- "host",
- "port",
- "namespaces"
- ],
- "properties": {
- "host": {
- "$id": "#/properties/db/properties/host",
- "type": "string",
- "title": "The Host Schema",
- "default": "",
- "examples": [
- "localhost"
- ],
- "pattern": "^(.*)$"
- },
- "port": {
- "$id": "#/properties/db/properties/port",
- "type": "integer",
- "title": "The Port Schema",
- "default": 0,
- "examples": [
- 6379
- ]
- },
- "namespaces": {
- "$id": "#/properties/db/properties/namespaces",
- "type": "array",
- "title": "The Namespaces Schema",
- "items": {
- "$id": "#/properties/db/properties/namespaces/items",
- "type": "string",
- "title": "The Items Schema",
- "default": "",
- "examples": [
- "sdl",
- "rnib"
- ],
- "pattern": "^(.*)$"
- }
- }
- }
- },
- "controls": {
- "$id": "#/properties/controls",
- "type": "object",
- "title": "The Controls Schema",
- "required": [
- "active",
- "requestorId",
- "ranFunctionId",
- "ricActionId",
- "interfaceId"
- ],
- "properties": {
- "active": {
- "$id": "#/properties/controls/properties/active",
- "type": "boolean",
- "title": "The Active Schema",
- "default": false,
- "examples": [
- true
- ]
- },
- "requestorId": {
- "$id": "#/properties/controls/properties/requestorId",
- "type": "integer",
- "title": "The Requestorid Schema",
- "default": 0,
- "examples": [
- 66
- ]
- },
- "ranFunctionId": {
- "$id": "#/properties/controls/properties/ranFunctionId",
- "type": "integer",
- "title": "The Ranfunctionid Schema",
- "default": 0,
- "examples": [
- 1
- ]
- },
- "ricActionId": {
- "$id": "#/properties/controls/properties/ricActionId",
- "type": "integer",
- "title": "The Ricactionid Schema",
- "default": 0,
- "examples": [
- 0
- ]
- },
- "interfaceId": {
- "$id": "#/properties/controls/properties/interfaceId",
- "type": "object",
- "title": "The Interfaceid Schema",
- "required": [
- "globalENBId"
- ],
- "properties": {
- "globalENBId": {
- "$id": "#/properties/controls/properties/interfaceId/properties/globalENBId",
- "type": "object",
- "title": "The Globalenbid Schema",
- "required": [
- "plmnId",
- "eNBId"
- ],
- "properties": {
- "plmnId": {
- "$id": "#/properties/controls/properties/interfaceId/properties/globalENBId/properties/plmnId",
- "type": "string",
- "title": "The Plmnid Schema",
- "default": "",
- "examples": [
- "43962"
- ],
- "pattern": "^(.*)$"
- },
- "eNBId": {
- "$id": "#/properties/controls/properties/interfaceId/properties/globalENBId/properties/eNBId",
- "type": "string",
- "title": "The Enbid Schema",
- "default": "",
- "examples": [
- "43962"
- ],
- "pattern": "^(.*)$"
- }
- }
- }
- }
- }
- }
- },
- "metrics": {
- "$id": "#/properties/metrics",
- "type": "array",
- "title": "The Metrics Schema",
- "items": {
- "$id": "#/properties/metrics/items",
- "type": "object",
- "title": "The Items Schema",
- "required": [
- "name",
- "type",
- "enabled",
- "description"
- ],
- "properties": {
- "name": {
- "$id": "#/properties/metrics/items/properties/name",
- "type": "string",
- "title": "The Name Schema",
- "default": "",
- "examples": [
- "UEContextCreated"
- ],
- "pattern": "^(.*)$"
- },
- "type": {
- "$id": "#/properties/metrics/items/properties/type",
- "type": "string",
- "title": "The Type Schema",
- "default": "",
- "examples": [
- "counter"
- ],
- "pattern": "^(.*)$"
- },
- "enabled": {
- "$id": "#/properties/metrics/items/properties/enabled",
- "type": "boolean",
- "title": "The Enabled Schema",
- "default": false,
- "examples": [
- true
- ]
- },
- "description": {
- "$id": "#/properties/metrics/items/properties/description",
- "type": "string",
- "title": "The Description Schema",
- "default": "",
- "examples": [
- "The total number of UE context creation events"
- ],
- "pattern": "^(.*)$"
- }
- }
- }
- }
- }
- },
"config": {
"local": {
"host": ":8080"
"description": "The total number of UE context release events"
}
]
- },
- "layout": [
- {
- "key": "controls.active",
- "title": "Active"
- },
- {
- "key": "controls.requestorId",
- "title": "Requestor Id"
- },
- {
- "key": "controls.ranFunctionId",
- "title": "RAN Function Id"
- },
- {
- "key": "controls.ricActionId",
- "title": "RIC Action Id"
- },
- {
- "key": "controls.interfaceId.globalENBId",
- "title": "Global ENB Id"
- },
- {
- "type": "flex",
- "flex-flow": "row wrap",
- "items": [
- {
- "key": "controls.interfaceId.globalENBId.plmnId",
- "title": "Plmn Id"
- },
- {
- "key": "controls.interfaceId.globalENBId.eNBId",
- "title": "ENB Id"
-
- }
- ]
- }
- ]
+ }
}
]
\ No newline at end of file
Version 2.1.0, 26 Aug 2020
--------------------------
+* Update the workflow of configure running Xapp in Dashboard (`OAM-110 <https://jira.o-ran-sc.org/browse/OAM-110>`_)
* Extend the Dashboard Xapp deploy workflow to accept configuration (`OAM-109 <https://jira.o-ran-sc.org/browse/OAM-109>`_)
* Add Xapp Onboarder client to backend (`OAM-108 <https://jira.o-ran-sc.org/browse/OAM-108>`_)
* Add Xapp Onboarder frontend UI (`OAM-108 <https://jira.o-ran-sc.org/browse/OAM-108>`_)