aboutsummaryrefslogtreecommitdiffstats
path: root/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src
diff options
context:
space:
mode:
authorMukesh Paliwal <mukesh.paliwal1@huawei.com>2021-06-24 11:54:21 +0530
committerMukesh Paliwal <mukesh.paliwal1@huawei.com>2021-06-24 11:54:21 +0530
commita5778f6f60d56686656411fbe927ba6ef472a4b4 (patch)
treeb0494235cf7a8b8cc6f7ed5bc25b17981cef4819 /so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src
parent8f8791fb45cd9c135fa269dc15be2c39ab5817c4 (diff)
Dynamic BPMN workflow GUI
Issue-ID: SO-3681 Signed-off-by: mukesh.paliwal <mukesh.paliwal1@huawei.com> Change-Id: Ia9e64dbb12fc45c0da73d67f64abb0ff0147d783
Diffstat (limited to 'so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src')
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/package.json1
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app-routing.module.ts6
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app.module.ts7
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/data.service.ts65
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/networkRecipe.model.ts12
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/recipeRequest.model.ts9
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/serviceRecipe.model.ts11
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/vnfRecipe.model.ts13
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.html183
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.scss178
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.spec.ts25
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.ts180
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.constant.ts31
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.html86
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.scss190
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.ts130
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/sidebar/sidebar.component.html5
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/styles.scss9
18 files changed, 1137 insertions, 4 deletions
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/package.json b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/package.json
index fcbeabe..4c3dfbd 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/package.json
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/package.json
@@ -27,6 +27,7 @@
"core-js": "^2.5.4",
"jquery": "^3.3.1",
"ngx-spinner": "^6.1.2",
+ "node-sass": "^4.14.1",
"rxjs": "^6.0.0",
"toastr": "^2.1.4",
"zone.js": "^0.8.26"
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app-routing.module.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app-routing.module.ts
index 428998d..ebe0909 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app-routing.module.ts
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app-routing.module.ts
@@ -24,6 +24,8 @@ import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { DetailsComponent } from './details/details.component';
+import { OnboardComponent } from './onboard/onboard.component';
+
const routes: Routes = [
{
@@ -35,6 +37,10 @@ const routes: Routes = [
// Route to page to show individual process based on ID
path: 'details/:id',
component: DetailsComponent
+ },
+ {
+ path: 'onboard',
+ component: OnboardComponent
}
];
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app.module.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app.module.ts
index 75be395..eee1398 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app.module.ts
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/app.module.ts
@@ -37,6 +37,8 @@ import { MatFormFieldModule, MatInputModule, MatTableModule, MatTabsModule, MatS
import { NgxSpinnerModule } from 'ngx-spinner';
import { RouterModule, Routes } from '@angular/router';
import { APP_BASE_HREF } from '@angular/common';
+import { OnboardComponent } from './onboard/onboard.component';
+import { RecipeComponent } from './recipe/recipe.component'
@NgModule({
declarations: [
@@ -44,7 +46,9 @@ import { APP_BASE_HREF } from '@angular/common';
SidebarComponent,
TopbarComponent,
HomeComponent,
- DetailsComponent
+ DetailsComponent,
+ OnboardComponent,
+ RecipeComponent
],
imports: [
BrowserModule,
@@ -68,6 +72,7 @@ import { APP_BASE_HREF } from '@angular/common';
RouterModule.forRoot([]),
ReactiveFormsModule
],
+ entryComponents: [RecipeComponent],
schemas: [
CUSTOM_ELEMENTS_SCHEMA
],
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/data.service.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/data.service.ts
index b391672..2e7f1e7 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/data.service.ts
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/data.service.ts
@@ -21,7 +21,7 @@ SPDX-License-Identifier: Apache-2.0
*/
import { Injectable } from '@angular/core';
-import { HttpClient, HttpErrorResponse } from '@angular/common/http';
+import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { BpmnInfraRequest } from './model/bpmnInfraRequest.model';
import { catchError } from 'rxjs/operators';
import { Observable } from 'rxjs';
@@ -37,7 +37,7 @@ import { ActivityInstance } from './model/activityInstance.model';
providedIn: 'root'
})
export class DataService {
-
+ httpOptions:any;
constructor(private http: HttpClient, private httpErrorHandlerService: HttpErrorHandlerService) { }
// HTTP POST call to running Spring Boot application
@@ -92,4 +92,65 @@ export class DataService {
catchError(this.httpErrorHandlerService.handleError("GET", url))
);
}
+
+ onboardBPMNInfra(formData: any): Observable<Object> {
+ var url = environment.soMonitoringBackendURL + 'workflowPackages/onboard';
+ return this.http.post<any>(url, formData)
+ .pipe(
+ catchError(this.httpErrorHandlerService.handleError("POST", url))
+ );
+ }
+
+ saveServiceRecipe(data: any): Observable<Object> {
+ this.httpOptions = {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ })
+ };
+ var url = environment.soMonitoringBackendURL + 'serviceRecipes';
+ return this.http.post<any>(url, data, this.httpOptions)
+ .pipe(
+ catchError(this.httpErrorHandlerService.handleError("POST", url))
+ );
+ }
+
+ getServiceRecipe(): Observable<Object> {
+ this.httpOptions = {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ })
+ };
+ var url = environment.soMonitoringBackendURL + 'serviceRecipes';
+ return this.http.get<any>(url, this.httpOptions)
+ .pipe(
+ catchError(this.httpErrorHandlerService.handleError("GET", url))
+ );
+ }
+
+ getNetworkRecipe(): Observable<Object> {
+ this.httpOptions = {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ })
+ };
+ var url = environment.soMonitoringBackendURL + 'networkRecipes';
+ return this.http.get<any>(url, this.httpOptions)
+ .pipe(
+ catchError(this.httpErrorHandlerService.handleError("GET", url))
+ );
+ }
+
+ getVnfRecipe(): Observable<Object> {
+ this.httpOptions = {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ })
+ };
+ var url = environment.soMonitoringBackendURL + 'vnfRecipes';
+ return this.http.get<any>(url, this.httpOptions)
+ .pipe(
+ catchError(this.httpErrorHandlerService.handleError("GET", url))
+ );
+ }
+
}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/networkRecipe.model.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/networkRecipe.model.ts
new file mode 100644
index 0000000..98a5fb7
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/networkRecipe.model.ts
@@ -0,0 +1,12 @@
+export interface NetworkRecipe {
+ id: string;
+ modelName: string;
+ paramXsd: string;
+ action: string;
+ description: string;
+ orchestrationUri: string;
+ recipeTimeout: string;
+ versionStr: string;
+ serviceType: string;
+ created: string;
+}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/recipeRequest.model.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/recipeRequest.model.ts
new file mode 100644
index 0000000..627246c
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/recipeRequest.model.ts
@@ -0,0 +1,9 @@
+export interface RecipeRequest {
+ modelName: string;
+ modelVersionId: string;
+ operation: string;
+ orchestrationFlow: string;
+ modelType: string;
+ orchestrationPackageName: string;
+ }
+ \ No newline at end of file
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/serviceRecipe.model.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/serviceRecipe.model.ts
new file mode 100644
index 0000000..67f5e6a
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/serviceRecipe.model.ts
@@ -0,0 +1,11 @@
+export interface ServiceRecipe {
+ id: string;
+ serviceModelUUID: string;
+ paramXsd: string;
+ action: string;
+ description: string;
+ orchestrationUri: string;
+ recipeTimeout: string;
+ serviceTimeoutInterim: string;
+ created: string;
+}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/vnfRecipe.model.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/vnfRecipe.model.ts
new file mode 100644
index 0000000..4c57524
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/model/vnfRecipe.model.ts
@@ -0,0 +1,13 @@
+export interface VnfRecipe {
+ id: string;
+ nfRole: string;
+ paramXsd: string;
+ vfModuleId: string;
+ action: string;
+ description: string;
+ orchestrationUri: string;
+ recipeTimeout: string;
+ versionStr: string;
+ serviceType: string;
+ created: string;
+ }
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.html b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.html
new file mode 100644
index 0000000..249ee7c
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.html
@@ -0,0 +1,183 @@
+
+<base href="/">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+<link rel="stylesheet" ng-href="./onboard.component.scss">
+<div class="completeForm">
+ <div>
+ <h3>Dynamic Deployment of workflow</h3>
+ </div>
+ <div class="uploadwar onboard-box" style="padding: 25px;">
+ <label>
+ Recipe war:
+ <span style="font-weight: bold;cursor: pointer;margin-left: 5px;" title="bpmn, groovy and java files">
+ ?
+ </span>
+ </label>
+ <br>
+ <input class="" type="file" class="upload-box form-control pad-top-not5"
+ (change)="beforeUpload($event)"
+ placeholder="Upload-BPMN-war" required>
+ <br>
+ <button (click)="onSubmit()" class="btn btn-primary">
+ Upload Recipe
+ </button>
+ </div>
+ <br />
+ <!-- Table to display selected fields if data present -->
+ <div class="example-container mat-elevation-z8">
+ <mat-tab-group class="tab-group" (focusChange)="changeTab($event)">
+ <mat-tab label="Service Recipe">
+ <mat-table [dataSource]="serviceRecipe" matSort>
+ <ng-container matColumnDef="serviceModelUUID">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Model UUID </mat-header-cell>
+ <mat-cell *matCellDef="let recipe">{{ recipe.serviceModelUUID }}</mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="paramXsd">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> ParamXsd </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.paramXsd }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="action">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Action </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.action }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="orchestrationUri">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Orchestration Uri </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.orchestrationUri }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="description">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Description </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.description }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="recipeTimeout">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Recipe Timeout </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.recipeTimeout }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="serviceTimeoutInterim">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Timeout Interim </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.serviceTimeoutInterim }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="created">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Created </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.created }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="operation">
+ <mat-header-cell *matHeaderCellDef>Operation</mat-header-cell>
+ <mat-cell *matCellDef="let recipe">
+ <button class="btn btn-primary" (click)="addRecipe(recipe)">Modify</button>
+ </mat-cell>
+ </ng-container>
+ <mat-header-row *matHeaderRowDef="displayedServiceColumns"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: displayedServiceColumns;"></mat-row>
+ </mat-table>
+ <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons>
+ </mat-paginator>
+ </mat-tab>
+ <mat-tab label="Network Recipe">
+ <mat-table [dataSource]="networkRecipe" matSort>
+ <ng-container matColumnDef="modelName">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Model Name </mat-header-cell>
+ <mat-cell *matCellDef="let recipe">{{ recipe.modelName }}</mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="paramXsd">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> ParamXsd </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.paramXsd }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="action">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Action </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.action }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="description">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Description </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.description }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="orchestrationUri">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Orchestration Uri </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.orchestrationUri }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="recipeTimeout">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Recipe Timeout </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.recipeTimeout }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="versionStr">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Version </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.versionStr }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="serviceType">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Type </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.serviceType }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="created">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Created </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.created }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="operation">
+ <mat-header-cell *matHeaderCellDef>Operation</mat-header-cell>
+ <mat-cell *matCellDef="let recipe">
+ <button class="btn btn-primary" (click)="addRecipe(recipe)">Modify</button>
+ </mat-cell>
+ </ng-container>
+ <mat-header-row *matHeaderRowDef="displayedNetworkColumns"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: displayedNetworkColumns;"></mat-row>
+ </mat-table>
+ <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons>
+ </mat-paginator>
+ </mat-tab>
+ <mat-tab label="VNF Recipe">
+ <mat-table [dataSource]="vnfRecipe" matSort>
+ <ng-container matColumnDef="nfRole">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> NF Role </mat-header-cell>
+ <mat-cell *matCellDef="let recipe">{{ recipe.nfRole }}</mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="paramXsd">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Param Xsd </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.paramXsd }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="vfModuleId">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> VFM Id </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.vfModuleId }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="action">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Action </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.action }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="description">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Description </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.description }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="orchestrationUri">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Orchestration Uri </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.orchestrationUri }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="recipeTimeout">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Recipe Timeout </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.recipeTimeout }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="versionStr">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Version </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.versionStr }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="serviceType">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Type </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.serviceType }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="created">
+ <mat-header-cell *matHeaderCellDef mat-sort-header> Created </mat-header-cell>
+ <mat-cell *matCellDef="let recipe"> {{ recipe.created }} </mat-cell>
+ </ng-container>
+ <ng-container matColumnDef="operation">
+ <mat-header-cell *matHeaderCellDef>Operation</mat-header-cell>
+ <mat-cell *matCellDef="let recipe">
+ <button class="btn btn-primary" (click)="addRecipe(recipe)">Modify</button>
+ </mat-cell>
+ </ng-container>
+ <mat-header-row *matHeaderRowDef="displayedVnfColumns"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: displayedVnfColumns;"></mat-row>
+ </mat-table>
+ <mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons>
+ </mat-paginator>
+ </mat-tab>
+ </mat-tab-group>
+ </div>
+</div>
+<ngx-spinner bdColor="rgba(51, 51, 51, 0.8)" size="large" color="#00285f" type="ball-spin-clockwise-fade-rotating"></ngx-spinner>
+<router-outlet></router-outlet>
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.scss b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.scss
new file mode 100644
index 0000000..7eff84f
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.scss
@@ -0,0 +1,178 @@
+.uploadwar {
+ background-color: white;
+ padding: 10px;
+ box-shadow: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);
+ }
+ .mat-form-field-appearance-legacy .mat-form-field-wrapper {
+ padding-bottom: 1.25em;
+ font-family: 'Montserrat', sans-serif;
+ }
+ .width-40p{
+ width: 40%!important;
+ }
+
+ .selectFilter {
+ width: 120px;
+ }
+
+ .valueInput {
+ width: 505px;
+ margin: 0;
+ }
+ .dispaly-flex{
+ display: flex;
+ }
+ .selectFilter.mat-select.ng-tns-c5-1.ng-star-inserted {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+ }
+
+ .mat-form-field-flex .valueInput {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+ }
+
+ .upload-box{
+ border: 1px solid gainsboro;
+ padding: 3px !important;
+ width: 30%;
+ margin-right: 15px;
+}
+
+.label-txt{
+ line-height: 45px;
+ text-align: left;
+}
+
+.container-home{
+ display: flex;
+ flex-direction: row;
+ /* align-items: center; */
+ justify-content: center;
+}
+.pad-top{
+ padding-top: 12px;
+}
+
+// .onboard-box{
+// display: flex;
+// flex-direction: row;
+// align-items: center;
+// justify-content: center;
+// }
+
+.selectHour,
+.selectMinute {
+ margin-left: 30px;
+ width: 100px;
+}
+.pad-top-not5{
+ padding-top: 0.5%;
+}
+.searchArea {
+ background-color: white;
+ padding: 10px;
+ height: 345px;
+ box-shadow: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);
+}
+
+.mat-form-field-appearance-legacy .mat-form-field-wrapper {
+ padding-bottom: 1.25em;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.selectFilter {
+ width: 120px;
+}
+
+.valueInput {
+ width: 400px;
+ margin-left: 30px;
+}
+
+.selectFilter.mat-select.ng-tns-c5-1.ng-star-inserted {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+}
+
+.mat-form-field-flex .valueInput {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+}
+
+.mat-primary .mat-option.mat-selected:not(.mat-option-disabled) {
+ color: #00285F;
+}
+
+.mat-option {
+ font-size: 17px;
+ line-height: 3em;
+ height: 3em;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.mat-select-arrow {
+ color: #00285F;
+}
+
+.mat-form-field.mat-focused.mat-primary .mat-select-arrow {
+ color: #00285F;
+}
+
+.mat-form-field-appearance-legacy .mat-form-field-underline {
+ color: #00285F;
+}
+
+.fa {
+ float: left;
+ width: 120px;
+ padding: 10px;
+ background: #2196F3;
+ color: white;
+ height: 40px;
+ font-size: 17px;
+ border: 1px solid grey;
+ border-left: none;
+ cursor: pointer;
+}
+
+form.example button:hover {
+ background: #0b7dda;
+}
+
+form.example::after {
+ content: "";
+ clear: both;
+ display: table;
+}
+
+.formFields {
+ display: inline-flex;
+}
+
+.endDate,
+.startDate {
+ margin-left: 90px;
+ width: 140px;
+}
+
+.selectHour,
+.selectMinute {
+ margin-left: 30px;
+ width: 100px;
+}
+
+#servStats {
+ background-color: white;
+ padding: 10px;
+ font-size: 17px;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.statsTable {
+ td {
+ padding: 12px 80px 12px 12px;
+ text-align: left;
+ border-bottom: 1px solid #ccc;
+ }
+}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.spec.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.spec.ts
new file mode 100644
index 0000000..a4e78e0
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { OnboardComponent } from './onboard.component';
+
+describe('OnboardComponent', () => {
+ let component: OnboardComponent;
+ let fixture: ComponentFixture<OnboardComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ OnboardComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OnboardComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.ts
new file mode 100644
index 0000000..e7e1d83
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.component.ts
@@ -0,0 +1,180 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { DataService } from '../data.service';
+import { NgxSpinnerService } from 'ngx-spinner';
+import { HttpClient } from '@angular/common/http';
+import { ToastrNotificationService } from '../toastr-notification-service.service';
+import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
+import { ServiceRecipe } from '../model/serviceRecipe.model';
+import { NetworkRecipe } from '../model/networkRecipe.model';
+import { VnfRecipe } from '../model/vnfRecipe.model';
+import { Constants } from './onboard.constant';
+import { MatDialog } from '@angular/material/dialog';
+import { RecipeComponent } from '../recipe/recipe.component';
+
+@Component({
+ selector: 'app-onboard',
+ templateUrl: './onboard.component.html',
+ styleUrls: ['./onboard.component.scss']
+})
+export class OnboardComponent implements OnInit {
+
+ constructor(private data: DataService, private spinner: NgxSpinnerService, private http: HttpClient,
+ private popup: ToastrNotificationService, public dialog: MatDialog) { }
+
+ fileList = [];
+ serviceRecipe: MatTableDataSource<ServiceRecipe>;
+ networkRecipe: MatTableDataSource<NetworkRecipe>;
+ vnfRecipe: MatTableDataSource<VnfRecipe>;
+
+ displayedServiceColumns = Constants.DISPLAYED_COLUMNS_SERVICE;
+ displayedNetworkColumns = Constants.DISPLAYED_COLUMNS_NETWORK;
+ displayedVnfColumns = Constants.DISPLAYED_COLUMNS_VNF;
+ pageSizeOptions = Constants.DEFAULT_PAGE_SIZE_OPTIONS;
+ currentTab:String = 'Service Recipe'
+
+ @ViewChild(MatPaginator) paginator: MatPaginator;
+ @ViewChild(MatSort) sort: MatSort;
+
+ ngOnInit() {
+ this.createFormControls();
+ this.getServiceRecipe()
+ }
+
+ createFormControls() {
+ let tabDiv = document.getElementsByClassName('mat-tab-label-container')
+ var bDiv = document.createElement("div");
+ bDiv.className = 'addRecipe';
+ var node = document.createElement("button");
+ node.className = 'btn btn-primary';
+ node.title = 'Click here to add recipes or update existing recipes in the SO-Catalog';
+ node.addEventListener("click", this.addRecipe.bind(this));
+ var textnode = document.createTextNode("Add Recipe");
+ node.appendChild(textnode);
+ bDiv.appendChild(node)
+ tabDiv[0].appendChild(bDiv);
+ }
+
+ changeTab(evt: any) {
+ if (evt.tab) {
+ this.currentTab = evt.tab.textLabel
+ }
+ if (this.currentTab === 'Network Recipe') {
+ this.getNetworkRecipe()
+ } else if (this.currentTab === 'VNF Recipe') {
+ this.getVnfRecipe()
+ } else {
+ this.getServiceRecipe()
+ }
+
+ }
+
+ addRecipe(evt: any) {
+ let isAdd = false;
+ if (evt.currentTarget) {
+ isAdd = true
+ }
+ const dialogRef = this.dialog.open(RecipeComponent, {
+ height: '500px',
+ width: '600px',
+ data: {
+ tab: this.currentTab,
+ addNew: isAdd,
+ fData: isAdd ? {} : evt
+ }
+ });
+ dialogRef.afterClosed().subscribe(result => {
+ console.log('The dialog was closed');
+ this.changeTab(this.currentTab)
+ });
+ }
+
+ getServiceRecipe () {
+ this.data.getServiceRecipe()
+ .subscribe((data: any) => {
+ console.log(JSON.stringify(data));
+ this.serviceRecipe = new MatTableDataSource<ServiceRecipe>(data.serviceRecipes);
+ this.serviceRecipe.sort = this.sort;
+ this.serviceRecipe.paginator = this.paginator;
+ this.serviceRecipe.paginator.firstPage();
+ },error => {
+ console.log(error);
+ console.log("Unable to store bpmn data, Error code:" + error.status);
+ this.spinner.hide();
+ });
+ }
+
+ getNetworkRecipe () {
+ this.data.getNetworkRecipe()
+ .subscribe((data: any) => {
+ this.networkRecipe = new MatTableDataSource<NetworkRecipe>(data.networkRecipes);
+ console.log(JSON.stringify(data));
+ },error => {
+ console.log(error);
+ console.log("Unable to store bpmn data, Error code:" + error.status);
+ this.spinner.hide();
+ });
+ }
+
+ getVnfRecipe () {
+ this.data.getVnfRecipe()
+ .subscribe((data: any) => {
+ this.vnfRecipe = new MatTableDataSource<VnfRecipe>(data.vnfRecipes);
+ console.log(JSON.stringify(data));
+ },error => {
+ console.log(error);
+ console.log("Unable to store bpmn data, Error code:" + error.status);
+ this.spinner.hide();
+ });
+ }
+
+ onSubmit() {
+ if(this.fileList.length > 0) {
+ this.handleUpload();
+ } else {
+ this.popup.error("Please select atleast one file.");
+ }
+ }
+
+ beforeUpload = (evt: any): boolean => {
+ this.fileList = [];
+ if(evt) {
+ let file = evt.currentTarget.files[0];
+ if(file.name.includes(".war")) {
+ this.fileList = this.fileList.concat(file);
+ } else {
+ this.popup.error("Invalid file format.");
+ }
+ }
+ return false;
+ };
+
+ handleUpload(): void {
+ if (this.fileList.length == 0) {
+ return;
+ }
+ this.spinner.show()
+ const formData = new FormData();
+ this.fileList.forEach((file: any) => {
+ formData.append('file', file, file.name);
+ });
+ this.data.onboardBPMNInfra(formData)
+ .subscribe((data: any) => {
+ this.spinner.hide();
+ console.log(JSON.stringify(data));
+ if(data != null) {
+ if(data.result == "true") {
+ this.popup.info(data.message);
+ } else if(data.errMsg) {
+ this.popup.error(data.errMsg);
+ } else {
+ this.popup.error(data.message);
+ }
+ }
+ },error => {
+ console.log(error);
+ this.popup.error("Unable to upload bpmn file, Error code:" + error.status);
+ this.spinner.hide();
+ });
+ }
+}
+
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.constant.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.constant.ts
new file mode 100644
index 0000000..b83f32c
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/onboard/onboard.constant.ts
@@ -0,0 +1,31 @@
+
+/**
+============LICENSE_START=======================================================
+ Copyright (C) 2019 Ericsson. All rights reserved.
+================================================================================
+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.
+
+SPDX-License-Identifier: Apache-2.0
+============LICENSE_END=========================================================
+
+@authors: andrei.barcovschi@ericsson.com, waqas.ikram@ericsson.com
+*/
+
+export class Constants {
+
+ public static DISPLAYED_COLUMNS_SERVICE = ['serviceModelUUID', 'paramXsd', 'action', 'description', 'orchestrationUri', 'recipeTimeout', 'serviceTimeoutInterim', 'created', 'operation'];
+ public static DISPLAYED_COLUMNS_NETWORK = ['modelName', 'paramXsd', 'action', 'description', 'orchestrationUri', 'recipeTimeout', 'versionStr', 'serviceType', 'created', 'operation'];
+ public static DISPLAYED_COLUMNS_VNF = ['nfRole', 'paramXsd', 'vfModuleId', 'action', 'description', 'orchestrationUri', 'recipeTimeout', 'versionStr', 'serviceType', 'created', 'operation'];
+
+ public static DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
+}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.html b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.html
new file mode 100644
index 0000000..eddae28
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.html
@@ -0,0 +1,86 @@
+<h1 mat-dialog-title style="font-size: 25px;">{{this.parentData.addNew ? 'Add Recipe' : 'Update Recipe'}}</h1>
+<hr>
+<div mat-dialog-content>
+ <div class="container">
+ <form novalidate
+ [formGroup]="myform"
+ (ngSubmit)="onSubmit()">
+ <div class="form-group"
+ *ngIf="modeType == 'Network Recipe'"
+ [ngClass]="{
+ 'has-danger': modelName.invalid && (modelName.dirty || modelName.touched),
+ 'has-success': modelName.valid && (modelName.dirty || modelName.touched)
+ }">
+ <label>Model Name</label>
+ <input type="text"
+ class="form-control"
+ formControlName="modelName"
+ required>
+ </div>
+ <div class="form-group"
+ *ngIf="modeType == 'VNF Recipe'"
+ [ngClass]="{
+ 'has-danger': modelName.invalid && (modelName.dirty || modelName.touched),
+ 'has-success': modelName.valid && (modelName.dirty || modelName.touched)
+ }">
+ <label>NF Role</label>
+ <input type="text"
+ class="form-control"
+ formControlName="nfRole"
+ required>
+ </div>
+ <div class="form-group"
+ [ngClass]="{
+ 'has-danger': modelVersionId.invalid && (modelVersionId.dirty || modelVersionId.touched),
+ 'has-success': modelVersionId.valid && (modelVersionId.dirty || modelVersionId.touched)
+ }">
+ <label>{{modeType == 'Service Recipe' ? 'Service Model UUID' : 'Model Versison ID'}}</label>
+ <input type="text"
+ class="form-control"
+ formControlName="modelVersionId"
+ required>
+ </div>
+ <div class="form-group"
+ [ngClass]="{
+ 'has-danger': operation.invalid && (operation.dirty || operation.touched),
+ 'has-success': operation.valid && (operation.dirty || operation.touched)
+ }">
+ <label>Action</label>
+ <input type="operation"
+ class="form-control"
+ formControlName="operation"
+ required>
+ </div>
+ <div class="form-group"
+ [ngClass]="{
+ 'has-danger': orchestrationFlow.invalid && (orchestrationFlow.dirty || orchestrationFlow.touched),
+ 'has-success': orchestrationFlow.valid && (orchestrationFlow.dirty || orchestrationFlow.touched)
+ }">
+ <label>Orchestration URI</label>
+ <input type="orchestrationFlow"
+ class="form-control"
+ formControlName="orchestrationFlow"
+ required>
+ </div>
+ <div class="form-group"
+ *ngIf="modeType == 'Service Recipe'"
+ [ngClass]="{
+ 'has-danger': modelName.invalid && (modelName.dirty || modelName.touched),
+ 'has-success': modelName.valid && (modelName.dirty || modelName.touched)
+ }">
+ <label>Recipe Timeout</label>
+ <input type="text"
+ class="form-control"
+ formControlName="recipeTimeout"
+ required>
+ </div>
+ <button style="margin-right: 10px;"
+ class="btn btn-primary"
+ (click)="closeDialog($event)">Cancel
+ </button>
+ <button type="submit"
+ class="btn btn-primary">Submit
+ </button>
+ </form>
+ </div>
+</div> \ No newline at end of file
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.scss b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.scss
new file mode 100644
index 0000000..bd1fe48
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.scss
@@ -0,0 +1,190 @@
+.uploadwar {
+ background-color: white;
+ padding: 10px;
+ box-shadow: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);
+ }
+ .mat-form-field-appearance-legacy .mat-form-field-wrapper {
+ padding-bottom: 1.25em;
+ font-family: 'Montserrat', sans-serif;
+ }
+ .width-40p{
+ width: 40%!important;
+ }
+
+ .selectFilter {
+ width: 120px;
+ }
+
+ .valueInput {
+ width: 505px;
+ margin: 0;
+ }
+ .dispaly-flex{
+ display: flex;
+ }
+ .selectFilter.mat-select.ng-tns-c5-1.ng-star-inserted {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+ }
+
+ .mat-form-field-flex .valueInput {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+ }
+
+ .upload-box{
+ border: 1px solid gainsboro;
+ padding: 8px;
+ width: 100%;
+}
+
+.label-txt{
+ line-height: 45px;
+ text-align: left;
+}
+
+.container-home{
+ display: flex;
+ flex-direction: row;
+ /* align-items: center; */
+ justify-content: center;
+}
+.pad-top{
+ padding-top: 12px;
+}
+
+// .onboard-box{
+// display: flex;
+// flex-direction: row;
+// align-items: center;
+// justify-content: center;
+// }
+
+.selectHour,
+.selectMinute {
+ margin-left: 30px;
+ width: 100px;
+}
+.pad-top-not5{
+ padding-top: 0.5%;
+}
+.searchArea {
+ background-color: white;
+ padding: 10px;
+ height: 345px;
+ box-shadow: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);
+}
+
+.mat-form-field-appearance-legacy .mat-form-field-wrapper {
+ padding-bottom: 1.25em;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.selectFilter {
+ width: 120px;
+}
+
+.valueInput {
+ width: 400px;
+ margin-left: 30px;
+}
+
+.selectFilter.mat-select.ng-tns-c5-1.ng-star-inserted {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+}
+
+.mat-form-field-flex .valueInput {
+ font-family: 'Montserrat', sans-serif;
+ font-size: 17px;
+}
+
+.mat-primary .mat-option.mat-selected:not(.mat-option-disabled) {
+ color: #00285F;
+}
+
+.mat-option {
+ font-size: 17px;
+ line-height: 3em;
+ height: 3em;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.mat-select-arrow {
+ color: #00285F;
+}
+
+.mat-form-field.mat-focused.mat-primary .mat-select-arrow {
+ color: #00285F;
+}
+
+.mat-form-field-appearance-legacy .mat-form-field-underline {
+ color: #00285F;
+}
+
+.fa {
+ float: left;
+ width: 120px;
+ padding: 10px;
+ background: #2196F3;
+ color: white;
+ height: 40px;
+ font-size: 17px;
+ border: 1px solid grey;
+ border-left: none;
+ cursor: pointer;
+}
+
+form.example button:hover {
+ background: #0b7dda;
+}
+
+form.example::after {
+ content: "";
+ clear: both;
+ display: table;
+}
+
+.formFields {
+ display: inline-flex;
+}
+
+.endDate,
+.startDate {
+ margin-left: 90px;
+ width: 140px;
+}
+
+.selectHour,
+.selectMinute {
+ margin-left: 30px;
+ width: 100px;
+}
+
+#servStats {
+ background-color: white;
+ padding: 10px;
+ font-size: 17px;
+ font-family: 'Montserrat', sans-serif;
+}
+
+.statsTable {
+ td {
+ padding: 12px 80px 12px 12px;
+ text-align: left;
+ border-bottom: 1px solid #ccc;
+ }
+}
+
+.mat-tab-label-container {
+ button {
+ height: 15px !important;
+ cursor: pointer !important;
+ height: 36px;
+ margin: 5px 10px;
+ }
+}
+
+input.ng-invalid.ng-touched {
+ border: 1px solid red;
+}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.ts b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.ts
new file mode 100644
index 0000000..cbe8a72
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/recipe/recipe.component.ts
@@ -0,0 +1,130 @@
+import { Component, OnInit, Inject } from '@angular/core';
+import { DataService } from '../data.service';
+import { NgxSpinnerService } from 'ngx-spinner';
+import { FormGroup, FormControl, Validators } from '@angular/forms';
+import { HttpClient } from '@angular/common/http';
+import { ToastrNotificationService } from '../toastr-notification-service.service';
+import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
+
+@Component({
+ selector: 'app-recipe',
+ templateUrl: './recipe.component.html',
+ styleUrls: ['./recipe.component.scss']
+})
+export class RecipeComponent implements OnInit {
+
+ constructor(private data: DataService, private spinner: NgxSpinnerService, private http: HttpClient,
+ private popup: ToastrNotificationService,public dialogRef: MatDialogRef<RecipeComponent>,
+ @Inject(MAT_DIALOG_DATA) public parentData: any) { }
+
+ fileList = [];
+ myform: FormGroup;
+ modelName: FormControl;
+ recipeTimeout: FormControl;
+ nfRole: FormControl;
+ modelVersionId: FormControl;
+ operation: FormControl;
+ orchestrationFlow: FormControl;
+ isCancel: boolean = false;
+ modeType: string = this.parentData.tab;
+
+ ngOnInit() {
+ this.createFormControls();
+ this.createForm();
+ }
+
+ createFormControls() {
+ let dd: any;
+ if (!this.parentData.addNew) {
+ let dd = this.parentData.fData;
+ this.modelName = new FormControl(dd.modelName);
+ if (dd.tab === 'Service Recipe') {
+ this.modelVersionId = new FormControl(dd.serviceModelUUID);
+ } else {
+ this.modelVersionId = new FormControl(dd.versionStr);
+ }
+ if (dd.tab === 'Network Recipe') {
+ this.nfRole = new FormControl(dd.nfRole,);
+ } else {
+ this.nfRole = new FormControl('',);
+ }
+ this.recipeTimeout = new FormControl(dd.recipeTimeout);
+ this.operation = new FormControl(dd.action,);
+ this.orchestrationFlow = new FormControl(dd.orchestrationUri,);
+ } else {
+ this.modelName = new FormControl('', );
+ this.modelVersionId = new FormControl('', );
+ this.operation = new FormControl('', );
+ this.orchestrationFlow = new FormControl('',);
+ this.nfRole = new FormControl('',);
+ this.recipeTimeout = new FormControl('',);
+ }
+ }
+
+ getModelType (type: string) {
+ if(type == 'Service Recipe') {
+ return 'Service'
+ } else if(type == 'Network Recipe') {
+ return 'Network'
+ } else {
+ return 'VNF'
+ }
+ }
+
+ createForm() {
+ this.myform = new FormGroup({
+ modelName: this.modelName,
+ nfRole: this.nfRole,
+ recipeTimeout: this.recipeTimeout,
+ modelVersionId: this.modelVersionId,
+ operation: this.operation,
+ orchestrationFlow: this.orchestrationFlow,
+ });
+ if(this.parentData.isAdd === false) {
+ this.myform = this.parentData.fData;
+ }
+ }
+
+ onSubmit() {
+ if (this.isCancel) {
+ return;
+ }
+ if (this.myform.valid ) {
+ console.log("Form Submitted!");
+ console.log("formdata", this.myform.value)
+ let data = this.myform.value;
+ data['modelType'] = this.getModelType(this.parentData.tab);
+ this.saveServiceRecipes(JSON.stringify(data));
+ this.myform.reset();
+ } else {
+ this.popup.error("Please fill valid data.");
+ }
+ }
+
+ closeDialog (evt: any) {
+ this.isCancel = true
+ this.dialogRef.close()
+ }
+
+ saveServiceRecipes(data: any): void {
+ this.data.saveServiceRecipe(data)
+ .subscribe((data: any) => {
+ console.log(JSON.stringify(data));
+ if(data != null) {
+ if (data.id && data.id != "") {
+ this.popup.info("Data stored in database.");
+ } else if(data.errMsg) {
+ this.popup.error(data.errMsg);
+ }
+ }
+ this.spinner.hide();
+ this.dialogRef.close()
+ },error => {
+ console.log(error);
+ this.popup.error("Unable to store bpmn data, Error code:" + error.status);
+ this.spinner.hide();
+ this.dialogRef.close()
+ });
+ }
+}
+
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/sidebar/sidebar.component.html b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/sidebar/sidebar.component.html
index 4b8edbe..fb36be5 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/sidebar/sidebar.component.html
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/app/sidebar/sidebar.component.html
@@ -26,4 +26,9 @@ SPDX-License-Identifier: Apache-2.0
<a routerLink="/">Home</a>
</li>
</ul>
+ <ul>
+ <li>
+ <a routerLink="/onboard">Update Recipe</a>
+ </li>
+ </ul>
</nav>
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/styles.scss b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/styles.scss
index 8457059..99dff22 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/styles.scss
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/src/main/frontend/src/styles.scss
@@ -28,7 +28,14 @@ body {
font-family: 'Montserrat', sans-serif;
height: 100vh;
}
-
+.addRecipe {
+ button {
+ height: 15px !important;
+ cursor: pointer !important;
+ height: 36px !important;
+ margin: 5px 10px !important;
+ }
+}
#container {
display: grid;
grid-template-columns: 70px auto;