summaryrefslogtreecommitdiffstats
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
parent8f8791fb45cd9c135fa269dc15be2c39ab5817c4 (diff)
Dynamic BPMN workflow GUI
Issue-ID: SO-3681 Signed-off-by: mukesh.paliwal <mukesh.paliwal1@huawei.com> Change-Id: Ia9e64dbb12fc45c0da73d67f64abb0ff0147d783
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/pom.xml4
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/JerseyConfiguration.java2
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/ServiceRecipe.java95
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/SoMonitoringController.java205
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/resources/application.yaml2
-rw-r--r--so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/.gitignore27
-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
24 files changed, 1472 insertions, 4 deletions
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/pom.xml b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/pom.xml
index 5e6d7ea..c9dbd60 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/pom.xml
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/pom.xml
@@ -34,6 +34,10 @@
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/JerseyConfiguration.java b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/JerseyConfiguration.java
index 22a1583..2a6bb81 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/JerseyConfiguration.java
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/JerseyConfiguration.java
@@ -21,6 +21,7 @@ package org.onap.so.monitoring.rest.api;
import javax.annotation.PostConstruct;
import javax.ws.rs.ApplicationPath;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
@@ -34,6 +35,7 @@ public class JerseyConfiguration extends ResourceConfig {
@PostConstruct
public void setUp() {
register(SoMonitoringController.class);
+ register(MultiPartFeature.class);
}
}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/ServiceRecipe.java b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/ServiceRecipe.java
new file mode 100644
index 0000000..f31438d
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/ServiceRecipe.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) 2020 Huawei, Inc. and others. 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.
+ */
+package org.onap.so.monitoring.rest.api;
+
+import com.fasterxml.jackson.annotation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({"warFile", "savetoDB", "modelName", "modelVersionId", "operation", "orchestrationFlow",
+ "modelType"})
+public class ServiceRecipe {
+ @JsonProperty("warFile")
+ private String warFile;
+ @JsonProperty("savetoDB")
+ private String savetoDB;
+ @JsonProperty("modelName")
+ private String modelName;
+ @JsonProperty("modelVersionId")
+ private String modelVersionId;
+ @JsonProperty("operation")
+ private String operation;
+ @JsonProperty("orchestrationFlow")
+ private String orchestrationFlow;
+ @JsonProperty("modelType")
+ private String modelType;
+
+ public String getWarFile() {
+ return warFile;
+ }
+
+ public void setWarFile(String warFile) {
+ this.warFile = warFile;
+ }
+
+ public String getSavetoDB() {
+ return savetoDB;
+ }
+
+ public void setSavetoDB(String savetoDB) {
+ this.savetoDB = savetoDB;
+ }
+
+ public String getModelName() {
+ return modelName;
+ }
+
+ public void setModelName(String modelName) {
+ this.modelName = modelName;
+ }
+
+ public String getModelVersionId() {
+ return modelVersionId;
+ }
+
+ public void setModelVersionId(String modelVersionId) {
+ this.modelVersionId = modelVersionId;
+ }
+
+ public String getOperation() {
+ return operation;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation;
+ }
+
+ public String getOrchestrationFlow() {
+ return orchestrationFlow;
+ }
+
+ public void setOrchestrationFlow(String orchestrationFlow) {
+ this.orchestrationFlow = orchestrationFlow;
+ }
+
+ public String getModelType() {
+ return modelType;
+ }
+
+ public void setModelType(String modelType) {
+ this.modelType = modelType;
+ }
+}
+
+
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/SoMonitoringController.java b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/SoMonitoringController.java
index 5a5a414..c2514c3 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/SoMonitoringController.java
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/java/org/onap/so/monitoring/rest/api/SoMonitoringController.java
@@ -19,9 +19,15 @@
*/
package org.onap.so.monitoring.rest.api;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.List;
import java.util.Map;
+import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -31,6 +37,8 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataParam;
import org.onap.so.monitoring.db.service.DatabaseServiceProvider;
import org.onap.so.monitoring.model.ActivityInstanceDetail;
import org.onap.so.monitoring.model.ProcessDefinitionDetail;
@@ -45,7 +53,13 @@ import org.onap.so.rest.exceptions.RestProcessingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
/**
* @author waqas.ikram@ericsson.com
@@ -63,6 +77,12 @@ public class SoMonitoringController {
private final CamundaProcessDataServiceProvider camundaProcessDataServiceProvider;
@Autowired
+ RestTemplate restTemplate;
+
+ @Value("${bpmn.url}")
+ private String bpmnBaseUrl;
+
+ @Autowired
public SoMonitoringController(final DatabaseServiceProvider databaseServiceProvider,
final CamundaProcessDataServiceProvider camundaProcessDataServiceProvider) {
this.databaseServiceProvider = databaseServiceProvider;
@@ -231,4 +251,189 @@ public class SoMonitoringController {
}
}
+ /**
+ * upload a workflow package to the server
+ *
+ * @param uploadInputStream upload stream
+ * @param disposition
+ * @return
+ */
+ @POST
+ @Path("/workflowPackages/onboard")
+ @Consumes("multipart/form-data")
+ @Produces("application/json")
+ public Response onboardWorkflowPackage(@FormDataParam("file") InputStream uploadedInputStream,
+ @FormDataParam("file") FormDataContentDisposition fileDetail) {
+ try {
+ LOGGER.info("SoMonitoringController onboardWorkflowPackage inputs {} ,:{}", uploadedInputStream,
+ fileDetail);
+
+ File file = new File(fileDetail.getFileName());
+ copyInputStreamToFile(uploadedInputStream, file);
+
+ RestTemplate rest = new RestTemplate();
+ org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
+ headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA);
+
+ MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
+
+ FileSystemResource value = new FileSystemResource(file);
+ body.add("file", value);
+
+ org.springframework.http.HttpEntity<MultiValueMap<String, Object>> requestEntity =
+ new org.springframework.http.HttpEntity<>(body, headers);
+ LOGGER.info("SoMonitoringController onboardWorkflowPackage request to be send :{}", requestEntity);
+
+ ResponseEntity<String> responseEntity =
+ rest.postForEntity(bpmnBaseUrl + "/workflowPackages/onboard", requestEntity, String.class);
+
+ LOGGER.info("SoMonitoringController onboardWorkflowPackage response recieved ::{}", responseEntity);
+
+ return Response.status(200).header("Access-Control-Allow-Origin", "*").entity(responseEntity.getBody())
+ .build();
+ } catch (Exception e) {
+ LOGGER.info("SoMonitoringController onboardWorkflowPackage error {} ", e.getMessage());
+ return Response.status(200).header("Access-Control-Allow-Origin", "*")
+ .entity("{\"errMsg\":\"Unable to process.\"}").build();
+ }
+ }
+
+
+ private static void copyInputStreamToFile(InputStream inputStream, File file) throws IOException {
+
+ try (FileOutputStream outputStream = new FileOutputStream(file)) {
+
+ int read;
+ byte[] bytes = new byte[1024];
+
+ while ((read = inputStream.read(bytes)) != -1) {
+ outputStream.write(bytes, 0, read);
+
+ }
+
+ }
+
+ }
+
+ @POST
+ @Path("/serviceRecipes")
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response setServiceRecipes(final ServiceRecipe requestBody) {
+ ObjectMapper objectMapper = new ObjectMapper();
+ String requestBodyJson = null;
+ try {
+ requestBodyJson = objectMapper.writeValueAsString(requestBody);
+ LOGGER.info(" SoMonitoringController setServiceRecipes request recieved {}", requestBodyJson);
+
+ org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
+ headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
+ org.springframework.http.HttpEntity<String> requestEntity =
+ new org.springframework.http.HttpEntity<>(requestBodyJson, headers);
+
+ LOGGER.info("SoMonitoringController setServiceRecipes request to be send :{}", requestEntity);
+
+ ResponseEntity<String> responseEntity =
+ restTemplate.postForEntity(bpmnBaseUrl + "/serviceRecipes", requestEntity, String.class);
+ LOGGER.info("setServiceRecipes respone :{}", responseEntity);
+
+ return Response.status(200).header("Access-Control-Allow-Origin", "*").entity(responseEntity.getBody())
+ .build();
+
+ } catch (Exception e) {
+ LOGGER.info("SoMonitoringController setServiceRecipes error: {}", e.getMessage());
+ return Response.status(200).header("Access-Control-Allow-Origin", "*")
+ .entity("{\"errMsg\":\"Unable to process.\"}").build();
+ }
+ }
+
+ @GET
+ @Path("/serviceRecipes")
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response getServiceRecipes() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ String requestBodyJson = null;
+ try {
+ LOGGER.info(" SoMonitoringController setServiceRecipes request recieved");
+
+ org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
+ headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
+ org.springframework.http.HttpEntity<String> requestEntity =
+ new org.springframework.http.HttpEntity<>(headers);
+
+ LOGGER.info("SoMonitoringController getServiceRecipes request to be send ");
+
+ ResponseEntity<String> responseEntity =
+ restTemplate.getForEntity(bpmnBaseUrl + "/serviceRecipes", String.class);
+ LOGGER.info("getServiceRecipes respone :{}", responseEntity);
+
+ return Response.status(200).header("Access-Control-Allow-Origin", "*").entity(responseEntity.getBody())
+ .build();
+
+ } catch (Exception e) {
+ LOGGER.info("SoMonitoringController setServiceRecipes error: {}", e.getMessage());
+ return Response.status(200).header("Access-Control-Allow-Origin", "*")
+ .entity("{\"errMsg\":\"Unable to process.\"}").build();
+ }
+ }
+
+ @GET
+ @Path("/networkRecipes")
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response getNetworkRecipes() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ String requestBodyJson = null;
+ try {
+ LOGGER.info(" SoMonitoringController setNetworkRecipes request recieved");
+
+ org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
+ headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
+ org.springframework.http.HttpEntity<String> requestEntity =
+ new org.springframework.http.HttpEntity<>(headers);
+
+ LOGGER.info("SoMonitoringController getNetworkRecipes request to be send ");
+
+ ResponseEntity<String> responseEntity =
+ restTemplate.getForEntity(bpmnBaseUrl + "/networkRecipes", String.class);
+ LOGGER.info("getNetworkRecipes respone :{}", responseEntity);
+
+ return Response.status(200).header("Access-Control-Allow-Origin", "*").entity(responseEntity.getBody())
+ .build();
+
+ } catch (Exception e) {
+ LOGGER.info("SoMonitoringController getNetworkRecipes error: {}", e.getMessage());
+ return Response.status(200).header("Access-Control-Allow-Origin", "*")
+ .entity("{\"errMsg\":\"Unable to process.\"}").build();
+ }
+ }
+
+ @GET
+ @Path("/vnfRecipes")
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response getVnfRecipes() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ String requestBodyJson = null;
+ try {
+ LOGGER.info(" SoMonitoringController getVnfRecipes request recieved");
+
+ org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
+ headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
+ org.springframework.http.HttpEntity<String> requestEntity =
+ new org.springframework.http.HttpEntity<>(headers);
+
+ LOGGER.info("SoMonitoringController getVnfRecipes request to be send ");
+
+ ResponseEntity<String> responseEntity =
+ restTemplate.getForEntity(bpmnBaseUrl + "/vnfRecipes", String.class);
+ LOGGER.info("getVnfRecipes respone :{}", responseEntity);
+
+ return Response.status(200).header("Access-Control-Allow-Origin", "*").entity(responseEntity.getBody())
+ .build();
+
+ } catch (Exception e) {
+ LOGGER.info("SoMonitoringController getVnfRecipes error: {}", e.getMessage());
+ return Response.status(200).header("Access-Control-Allow-Origin", "*")
+ .entity("{\"errMsg\":\"Unable to process.\"}").build();
+ }
+ }
+
}
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/resources/application.yaml b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/resources/application.yaml
index c57d79c..2b83fcf 100644
--- a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/resources/application.yaml
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-service/src/main/resources/application.yaml
@@ -29,3 +29,5 @@ spring:
username: demo
password: '$2a$10$ndkDhATUid4a3g0JJVRv2esX4rtB.vzCn7iBhKyR1qZ/wDdvNzjTS'
role: GUI-Client
+bpmn:
+ url: http://so-bpmn-infra.onap:8081/mso/hotmanagement
diff --git a/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/.gitignore b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/.gitignore
new file mode 100644
index 0000000..6cf36fd
--- /dev/null
+++ b/so-admin-cockpit-monitoring-workflow/so-admin-cockpit-monitoring-workflow-ui/.gitignore
@@ -0,0 +1,27 @@
+# compiled output
+dist
+dist-server
+tmp
+
+# dependencies
+node_modules
+node_modules/*
+
+# # IDEs and editors
+/.idea
+.project
+.classpath
+*.launch
+.settings/
+
+# e2e
+e2e/*.js
+e2e/*.map
+
+
+#java
+.project
+.idea/
+/target/
+.settings*
+.classpath
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;