Display Extend Activities on WF Designer UI. 11/39011/1
authorYuanHu <yuan.hu1@zte.com.cn>
Tue, 27 Mar 2018 09:58:42 +0000 (17:58 +0800)
committerYuanHu <yuan.hu1@zte.com.cn>
Tue, 27 Mar 2018 09:58:42 +0000 (17:58 +0800)
Display Extend Activities on WF Designer UI.
Use Extend Activities to Design Workflow and Save

Issue-ID: SDC-1130,SDC-1131

Change-Id: Iea62eb0edafb2270deaac89b458015e78d961cd0
Signed-off-by: YuanHu <yuan.hu1@zte.com.cn>
97 files changed:
sdc-workflow-designer-ui/.angular-cli.json
sdc-workflow-designer-ui/.editorconfig
sdc-workflow-designer-ui/README.md
sdc-workflow-designer-ui/package-lock.json
sdc-workflow-designer-ui/package.json
sdc-workflow-designer-ui/src/app/app.component.html
sdc-workflow-designer-ui/src/app/app.component.ts
sdc-workflow-designer-ui/src/app/app.module.ts
sdc-workflow-designer-ui/src/app/components/container/container.component.html
sdc-workflow-designer-ui/src/app/components/container/container.component.ts
sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.html
sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.ts
sdc-workflow-designer-ui/src/app/components/global-notice/global-notice.component.ts
sdc-workflow-designer-ui/src/app/components/menus/menus.component.html
sdc-workflow-designer-ui/src/app/components/menus/menus.component.ts
sdc-workflow-designer-ui/src/app/components/menus/rest-config/rest-config-detail/rest-config-detail.component.html
sdc-workflow-designer-ui/src/app/components/menus/rest-config/rest-config-detail/rest-config-detail.component.ts
sdc-workflow-designer-ui/src/app/components/menus/rest-config/rest-config-list/rest-config-list.component.html
sdc-workflow-designer-ui/src/app/components/menus/rest-config/rest-config-list/rest-config-list.component.ts
sdc-workflow-designer-ui/src/app/components/menus/rest-config/rest-config.component.html
sdc-workflow-designer-ui/src/app/components/menus/rest-config/rest-config.component.ts
sdc-workflow-designer-ui/src/app/components/menus/workflows/workflows.component.html [deleted file]
sdc-workflow-designer-ui/src/app/components/menus/workflows/workflows.component.ts [deleted file]
sdc-workflow-designer-ui/src/app/components/node-parameters/node-parameters.component.css [deleted file]
sdc-workflow-designer-ui/src/app/components/node-parameters/parameter-tree/parameter-tree.component.html [deleted file]
sdc-workflow-designer-ui/src/app/components/node/node.component.html
sdc-workflow-designer-ui/src/app/components/node/node.component.ts
sdc-workflow-designer-ui/src/app/components/parameter/parameter.component.html
sdc-workflow-designer-ui/src/app/components/parameter/parameter.component.ts
sdc-workflow-designer-ui/src/app/components/property/error-event/error-event.component.html
sdc-workflow-designer-ui/src/app/components/property/error-event/error-event.component.ts
sdc-workflow-designer-ui/src/app/components/property/intermediate-catch-event/intermediate-catch-event.component.html
sdc-workflow-designer-ui/src/app/components/property/intermediate-catch-event/intermediate-catch-event.component.ts
sdc-workflow-designer-ui/src/app/components/property/node-template/node-template.component.html
sdc-workflow-designer-ui/src/app/components/property/node-template/node-template.component.ts
sdc-workflow-designer-ui/src/app/components/property/properties.component.html
sdc-workflow-designer-ui/src/app/components/property/properties.component.ts
sdc-workflow-designer-ui/src/app/components/property/rest-task/node-parameters/node-parameters.component.html [moved from sdc-workflow-designer-ui/src/app/components/node-parameters/node-parameters.component.html with 50% similarity]
sdc-workflow-designer-ui/src/app/components/property/rest-task/node-parameters/node-parameters.component.ts [moved from sdc-workflow-designer-ui/src/app/components/node-parameters/node-parameters.component.ts with 52% similarity]
sdc-workflow-designer-ui/src/app/components/property/rest-task/node-parameters/parameter-tree/parameter-tree.component.css [moved from sdc-workflow-designer-ui/src/app/components/node-parameters/parameter-tree/parameter-tree.component.css with 100% similarity]
sdc-workflow-designer-ui/src/app/components/property/rest-task/node-parameters/parameter-tree/parameter-tree.component.html [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/property/rest-task/node-parameters/parameter-tree/parameter-tree.component.ts [moved from sdc-workflow-designer-ui/src/app/components/node-parameters/parameter-tree/parameter-tree.component.ts with 78% similarity]
sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.html [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.spec.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task.component.html
sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task.component.ts
sdc-workflow-designer-ui/src/app/components/property/script-task/script-task.component.html
sdc-workflow-designer-ui/src/app/components/property/script-task/script-task.component.ts
sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.html [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.spec.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/property/start-event/start-event.component.html
sdc-workflow-designer-ui/src/app/components/property/start-event/start-event.component.ts
sdc-workflow-designer-ui/src/app/components/sequence-flow/sequence-flow.component.html
sdc-workflow-designer-ui/src/app/components/sequence-flow/sequence-flow.component.ts
sdc-workflow-designer-ui/src/app/components/toolbar/toolbar-node/toolbar-node.component.html [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/toolbar/toolbar-node/toolbar-node.component.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.html
sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.ts
sdc-workflow-designer-ui/src/app/model/model.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/notice-type.enum.ts
sdc-workflow-designer-ui/src/app/model/plan-model.ts
sdc-workflow-designer-ui/src/app/model/rest-config.ts
sdc-workflow-designer-ui/src/app/model/swagger.ts
sdc-workflow-designer-ui/src/app/model/value-object.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/value-source.enum.ts
sdc-workflow-designer-ui/src/app/model/value-type.enum.ts
sdc-workflow-designer-ui/src/app/model/workflow/node-type.enum.ts
sdc-workflow-designer-ui/src/app/model/workflow/parameter.ts
sdc-workflow-designer-ui/src/app/model/workflow/rest-task.ts
sdc-workflow-designer-ui/src/app/model/workflow/script-task.ts
sdc-workflow-designer-ui/src/app/model/workflow/service-task.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/workflow/workflow-node.ts
sdc-workflow-designer-ui/src/app/services/auth.service.spec.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/auth.service.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/broadcast.service.ts
sdc-workflow-designer-ui/src/app/services/data/backend.service.ts [deleted file]
sdc-workflow-designer-ui/src/app/services/data/data.service.ts [deleted file]
sdc-workflow-designer-ui/src/app/services/data/in-memory-data.service.ts [deleted file]
sdc-workflow-designer-ui/src/app/services/data/mockdata.ts [deleted file]
sdc-workflow-designer-ui/src/app/services/data/sdc.service.ts [deleted file]
sdc-workflow-designer-ui/src/app/services/display-info.service.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/interface.service.spec.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/interface.service.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts
sdc-workflow-designer-ui/src/app/services/model.service.ts
sdc-workflow-designer-ui/src/app/services/node-type.service.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/rest.service.ts
sdc-workflow-designer-ui/src/app/services/setting.service.spec.ts
sdc-workflow-designer-ui/src/app/services/setting.service.ts
sdc-workflow-designer-ui/src/app/services/swagger-tree-converter.service.ts
sdc-workflow-designer-ui/src/app/services/tosca.service.spec.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/tosca.service.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/workflow.service.ts [deleted file]
sdc-workflow-designer-ui/src/favicon.ico [deleted file]
sdc-workflow-designer-ui/src/ngict-component.css [deleted file]

index 453d361..a4cf34e 100644 (file)
@@ -1,65 +1,65 @@
 {
-    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
-    "project": {
-        "name": "workflowmodeler"
-    },
-    "apps": [
-        {
-            "root": "src",
-            "outDir": "dist",
-            "assets": [
-                "assets",
-                "favicon.ico"
-            ],
-            "index": "index.html",
-            "main": "main.ts",
-            "polyfills": "polyfills.ts",
-            "test": "test.ts",
-            "tsconfig": "tsconfig.app.json",
-            "testTsconfig": "tsconfig.spec.json",
-            "prefix": "app",
-            "styles": [
-                "../node_modules/bootstrap/dist/css/bootstrap.min.css",
-                "../node_modules/font-awesome/css/font-awesome.min.css",
-                "../node_modules/primeng/resources/primeng.min.css",
-                "../node_modules/primeng/resources/themes/bootstrap/theme.css",
-                "ngict-component.css",
-                "styles.css"
-            ],
-            "scripts": [],
-            "environmentSource": "environments/environment.ts",
-            "environments": {
-                "dev": "environments/environment.ts",
-                "prod": "environments/environment.prod.ts"
-            }
-        }
-    ],
-    "e2e": {
-        "protractor": {
-            "config": "./protractor.conf.js"
-        }
+  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+  "project": {
+    "name": "workflow-modeler"
+  },
+  "apps": [
+    {
+      "root": "src",
+      "outDir": "dist",
+      "assets": [
+        "assets"
+      ],
+      "index": "index.html",
+      "main": "main.ts",
+      "polyfills": "polyfills.ts",
+      "test": "test.ts",
+      "tsconfig": "tsconfig.app.json",
+      "testTsconfig": "tsconfig.spec.json",
+      "prefix": "wfm",
+      "styles": [
+        "../node_modules/bootstrap/dist/css/bootstrap.css",
+        "../node_modules/font-awesome/css/font-awesome.css",
+        "../node_modules/primeng/resources/primeng.min.css",
+        "../node_modules/primeng/resources/themes/bootstrap/theme.css",
+        "app/paletx/assets/css/style.css",
+        "app/paletx/assets/themes/default/theme.css",
+        "styles.css"
+      ],
+      "scripts": [],
+      "environmentSource": "environments/environment.ts",
+      "environments": {
+        "dev": "environments/environment.ts",
+        "prod": "environments/environment.prod.ts"
+      }
+    }
+  ],
+  "e2e": {
+    "protractor": {
+      "config": "./protractor.conf.js"
+    }
+  },
+  "lint": [
+    {
+      "project": "src/tsconfig.app.json",
+      "exclude": "**/node_modules/**"
     },
-    "lint": [
-        {
-            "project": "src/tsconfig.app.json",
-            "exclude": "**/node_modules/**"
-        },
-        {
-            "project": "src/tsconfig.spec.json",
-            "exclude": "**/node_modules/**"
-        },
-        {
-            "project": "e2e/tsconfig.e2e.json",
-            "exclude": "**/node_modules/**"
-        }
-    ],
-    "test": {
-        "karma": {
-            "config": "./karma.conf.js"
-        }
+    {
+      "project": "src/tsconfig.spec.json",
+      "exclude": "**/node_modules/**"
     },
-    "defaults": {
-        "styleExt": "css",
-        "component": {}
+    {
+      "project": "e2e/tsconfig.e2e.json",
+      "exclude": "**/node_modules/**"
+    }
+  ],
+  "test": {
+    "karma": {
+      "config": "./karma.conf.js"
     }
+  },
+  "defaults": {
+    "styleExt": "css",
+    "component": {}
+  }
 }
index 9b73521..6e87a00 100644 (file)
@@ -4,7 +4,7 @@ root = true
 [*]
 charset = utf-8
 indent_style = space
-indent_size = 4
+indent_size = 2
 insert_final_newline = true
 trim_trailing_whitespace = true
 
index 03f57b7..88859be 100644 (file)
@@ -1,28 +1,57 @@
-# Workflow designer
 
-This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.3.1.
+# Workflow Modeler
 
-## Development server
+This project is an implementation of a workflow modeler for creating and maintaining [TOSCA] compatible management plans.
 
-Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+It is based on the thesis [Ein Modellierungswerkzeug für BPMN4TOSCA] by Thomas Michelbach.
 
-## Code scaffolding
+## Installation
 
-Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
+  Fetch dependencies using `npm install`
 
-## Build
+## Run
 
-Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
+Execute `npm start`.
+Open <http://localhost:9527/> with correct HTTP GET params:
 
-## Running unit tests
+repositoryURL (e.g. http://dev.winery.opentosca.org/winery/)
+namespace (e.g. http://www.example.org/ServiceTemplates)
+id (e.g. PlanDemonstration)
+plan (e.g. Test)
 
-Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+You can also directly embed it into Winery.
+Ensure that `winery.properties` contains following line.
 
-## Running end-to-end tests
+```
+bpmn4toscamodelerBaseURI=http://localhost:9527/
+```
 
-Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
-Before running the tests make sure you are serving the app via `ng serve`.
+## License
+Copyright (c) 2017 ZTE Corporation.
 
-## Further help
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the [Eclipse Public License v1.0]
+and the [Apache License v2.0] which both accompany this distribution,
+and are available at http://www.eclipse.org/legal/epl-v10.html
+and http://www.apache.org/licenses/LICENSE-2.0.
 
-To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
+Please check the [EPL FAQ](https://eclipse.org/legal/eplfaq.php#DUALLIC) for implications.
+
+ [Apache License v2.0]: http://www.apache.org/licenses/LICENSE-2.0.html
+ [Eclipse Public License v1.0]: http://www.eclipse.org/legal/epl-v10.html
+
+
+## Literature
+
+### About TOSCA
+* Binz, T., Breiter, G., Leymann, F., Spatzier, T.: Portable Cloud Services Using TOSCA. IEEE Internet Computing 16(03), 80--85 (May 2012). [DOI:10.1109/MIC.2012.43]
+* Topology and Orchestration Specification for Cloud Applications Version 1.0. 25 November 2013. OASIS Standard. http://docs.oasis-open.org/tosca/TOSCA/v1.0/os/TOSCA-v1.0-os.html
+* OASIS: Topology and Orchestration Specification for Cloud Applications (TOSCA) Primer Version 1.0 (2013)
+
+See http://www.opentosca.org/#publications for a list of publications in the OpenTOSCA ecosystem.
+
+ [Apache License v2.0]: http://www.apache.org/licenses/LICENSE-2.0.html
+ [DOI:10.1109/MIC.2012.43]: http://dx.doi.org/10.1109/MIC.2012.43
+ [Eclipse Public License v1.0]: http://www.eclipse.org/legal/epl-v10.html
+ [Ein Modellierungswerkzeug für BPMN4TOSCA]: http://elib.uni-stuttgart.de/opus/volltexte/2015/9943/
+ [TOSCA]: https://www.oasis-open.org/committees/tosca/
index a701545..5c4a9cb 100644 (file)
@@ -1,18 +1,43 @@
 {
-  "name": "workflow-designer",
+  "name": "workflow-modeler",
   "version": "1.0.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
-    "@angular-devkit/build-optimizer": {
-      "version": "0.0.13",
-      "resolved": "http://registry.npm.taobao.org/@angular-devkit/build-optimizer/download/@angular-devkit/build-optimizer-0.0.13.tgz",
-      "integrity": "sha1-zzl692q+iZqpCdSnNRBmlMofCM8=",
+    "@angular-devkit/core": {
+      "version": "0.0.20",
+      "resolved": "http://registry.npm.taobao.org/@angular-devkit/core/download/@angular-devkit/core-0.0.20.tgz",
+      "integrity": "sha1-KtNt0hD8zQ4VbQHGSZCCrUzYwq8=",
       "dev": true,
       "requires": {
-        "loader-utils": "1.1.0",
-        "source-map": "0.5.6",
-        "typescript": "2.3.4"
+        "source-map": "0.5.6"
+      }
+    },
+    "@angular-devkit/schematics": {
+      "version": "0.0.52",
+      "resolved": "http://registry.npm.taobao.org/@angular-devkit/schematics/download/@angular-devkit/schematics-0.0.52.tgz",
+      "integrity": "sha1-y9L0J3i1DWQiolT/rsBa1O88tsA=",
+      "dev": true,
+      "requires": {
+        "@ngtools/json-schema": "1.1.0",
+        "rxjs": "5.5.7"
+      },
+      "dependencies": {
+        "rxjs": {
+          "version": "5.5.7",
+          "resolved": "http://registry.npm.taobao.org/rxjs/download/rxjs-5.5.7.tgz",
+          "integrity": "sha1-r7PRZCsGmy+/IDkD1lAdGstM2ic=",
+          "dev": true,
+          "requires": {
+            "symbol-observable": "1.0.1"
+          }
+        },
+        "symbol-observable": {
+          "version": "1.0.1",
+          "resolved": "http://registry.npm.taobao.org/symbol-observable/download/symbol-observable-1.0.1.tgz",
+          "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
+          "dev": true
+        }
       }
     },
     "@angular/animations": {
       }
     },
     "@angular/cli": {
-      "version": "1.3.1",
-      "resolved": "http://registry.npm.taobao.org/@angular/cli/download/@angular/cli-1.3.1.tgz",
-      "integrity": "sha1-K8Kf1wkCTdOXExtM8a3BUCbmUF8=",
+      "version": "1.4.3",
+      "resolved": "http://registry.npm.taobao.org/@angular/cli/download/@angular/cli-1.4.3.tgz",
+      "integrity": "sha1-g4nU7q3+NKux0W5Tg2QWqPhDD7M=",
       "dev": true,
       "requires": {
-        "@angular-devkit/build-optimizer": "0.0.13",
+        "@angular-devkit/build-optimizer": "0.0.42",
+        "@angular-devkit/schematics": "0.0.52",
         "@ngtools/json-schema": "1.1.0",
-        "@ngtools/webpack": "1.6.1",
+        "@ngtools/webpack": "1.7.1",
+        "@schematics/angular": "0.0.49",
         "autoprefixer": "6.7.7",
         "chalk": "2.1.0",
         "circular-dependency-plugin": "3.0.0",
         "common-tags": "1.4.0",
+        "copy-webpack-plugin": "4.5.1",
         "core-object": "3.1.4",
         "css-loader": "0.28.5",
         "cssnano": "3.10.0",
         "denodeify": "1.2.1",
-        "diff": "3.3.0",
-        "ember-cli-normalize-entity-name": "1.0.0",
         "ember-cli-string-utils": "1.1.0",
         "exports-loader": "0.6.4",
         "extract-text-webpack-plugin": "3.0.0",
         "heimdalljs": "0.2.5",
         "heimdalljs-logger": "0.1.9",
         "html-webpack-plugin": "2.30.1",
-        "inflection": "1.12.0",
-        "inquirer": "3.2.2",
-        "isbinaryfile": "3.0.2",
         "istanbul-instrumenter-loader": "2.0.0",
         "karma-source-map-support": "1.2.0",
         "less": "2.7.2",
         "less-loader": "4.0.5",
-        "license-webpack-plugin": "0.5.1",
+        "license-webpack-plugin": "1.3.1",
         "lodash": "4.17.4",
         "memory-fs": "0.4.1",
-        "minimatch": "3.0.4",
         "node-modules-path": "1.0.1",
         "node-sass": "4.5.3",
         "nopt": "4.0.1",
         "postcss-url": "5.1.2",
         "raw-loader": "0.5.1",
         "resolve": "1.4.0",
-        "rsvp": "3.6.2",
         "rxjs": "5.4.3",
         "sass-loader": "6.0.6",
-        "script-loader": "0.7.0",
         "semver": "5.4.1",
         "silent-error": "1.1.0",
         "source-map-loader": "0.2.1",
         "style-loader": "0.13.2",
         "stylus": "0.54.5",
         "stylus-loader": "3.0.1",
-        "temp": "0.8.3",
-        "typescript": "2.3.4",
+        "typescript": "2.4.2",
         "url-loader": "0.5.9",
-        "walk-sync": "0.3.2",
+        "webpack": "3.5.6",
+        "webpack-concat-plugin": "1.4.0",
         "webpack-dev-middleware": "1.12.0",
-        "webpack-dev-server": "2.5.1",
+        "webpack-dev-server": "2.7.1",
         "webpack-merge": "4.1.0",
         "zone.js": "0.8.16"
+      },
+      "dependencies": {
+        "@angular-devkit/build-optimizer": {
+          "version": "0.0.42",
+          "resolved": "http://registry.npm.taobao.org/@angular-devkit/build-optimizer/download/@angular-devkit/build-optimizer-0.0.42.tgz",
+          "integrity": "sha1-QCsN2kiD25HiOBw93FWIhAiniU4=",
+          "dev": true,
+          "requires": {
+            "loader-utils": "1.1.0",
+            "source-map": "0.5.6",
+            "typescript": "2.6.2",
+            "webpack-sources": "1.0.1"
+          },
+          "dependencies": {
+            "typescript": {
+              "version": "2.6.2",
+              "resolved": "http://registry.npm.taobao.org/typescript/download/typescript-2.6.2.tgz",
+              "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=",
+              "dev": true
+            }
+          }
+        },
+        "@ngtools/webpack": {
+          "version": "1.7.1",
+          "resolved": "http://registry.npm.taobao.org/@ngtools/webpack/download/@ngtools/webpack-1.7.1.tgz",
+          "integrity": "sha1-OD3daJhFz0L8dVl19kQPdVNfUBY=",
+          "dev": true,
+          "requires": {
+            "enhanced-resolve": "3.4.1",
+            "loader-utils": "1.1.0",
+            "magic-string": "0.22.4",
+            "source-map": "0.5.6"
+          }
+        },
+        "camelcase": {
+          "version": "4.1.0",
+          "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz",
+          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+          "dev": true
+        },
+        "faye-websocket": {
+          "version": "0.11.1",
+          "resolved": "http://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.11.1.tgz",
+          "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
+          "dev": true,
+          "requires": {
+            "websocket-driver": "0.6.5"
+          }
+        },
+        "find-up": {
+          "version": "2.1.0",
+          "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz",
+          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+          "dev": true,
+          "requires": {
+            "locate-path": "2.0.0"
+          }
+        },
+        "has-flag": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-2.0.0.tgz",
+          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
+          "requires": {
+            "number-is-nan": "1.0.1"
+          }
+        },
+        "license-webpack-plugin": {
+          "version": "1.3.1",
+          "resolved": "http://registry.npm.taobao.org/license-webpack-plugin/download/license-webpack-plugin-1.3.1.tgz",
+          "integrity": "sha1-aIt2RyGI71l5GLfK4+7H3C+loOg=",
+          "dev": true,
+          "requires": {
+            "ejs": "2.5.8"
+          }
+        },
+        "load-json-file": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz",
+          "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "4.1.11",
+            "parse-json": "2.2.0",
+            "pify": "2.3.0",
+            "strip-bom": "3.0.0"
+          }
+        },
+        "os-locale": {
+          "version": "2.1.0",
+          "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-2.1.0.tgz",
+          "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=",
+          "dev": true,
+          "requires": {
+            "execa": "0.7.0",
+            "lcid": "1.0.0",
+            "mem": "1.1.0"
+          }
+        },
+        "path-type": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz",
+          "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+          "dev": true,
+          "requires": {
+            "pify": "2.3.0"
+          }
+        },
+        "read-pkg": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz",
+          "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+          "dev": true,
+          "requires": {
+            "load-json-file": "2.0.0",
+            "normalize-package-data": "2.4.0",
+            "path-type": "2.0.0"
+          }
+        },
+        "read-pkg-up": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz",
+          "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+          "dev": true,
+          "requires": {
+            "find-up": "2.1.0",
+            "read-pkg": "2.0.0"
+          }
+        },
+        "sockjs-client": {
+          "version": "1.1.4",
+          "resolved": "http://registry.npm.taobao.org/sockjs-client/download/sockjs-client-1.1.4.tgz",
+          "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=",
+          "dev": true,
+          "requires": {
+            "debug": "2.6.8",
+            "eventsource": "0.1.6",
+            "faye-websocket": "0.11.1",
+            "inherits": "2.0.3",
+            "json3": "3.3.2",
+            "url-parse": "1.1.9"
+          }
+        },
+        "strip-bom": {
+          "version": "3.0.0",
+          "resolved": "http://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz",
+          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "4.5.0",
+          "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-4.5.0.tgz",
+          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+          "dev": true,
+          "requires": {
+            "has-flag": "2.0.0"
+          }
+        },
+        "webpack": {
+          "version": "3.5.6",
+          "resolved": "http://registry.npm.taobao.org/webpack/download/webpack-3.5.6.tgz",
+          "integrity": "sha1-pJL7bB7X9XOBb5DgDI+7WiDMXDY=",
+          "dev": true,
+          "requires": {
+            "acorn": "5.1.1",
+            "acorn-dynamic-import": "2.0.2",
+            "ajv": "5.2.2",
+            "ajv-keywords": "2.1.0",
+            "async": "2.5.0",
+            "enhanced-resolve": "3.4.1",
+            "escope": "3.6.0",
+            "interpret": "1.0.3",
+            "json-loader": "0.5.7",
+            "json5": "0.5.1",
+            "loader-runner": "2.3.0",
+            "loader-utils": "1.1.0",
+            "memory-fs": "0.4.1",
+            "mkdirp": "0.5.1",
+            "node-libs-browser": "2.0.0",
+            "source-map": "0.5.6",
+            "supports-color": "4.5.0",
+            "tapable": "0.2.8",
+            "uglifyjs-webpack-plugin": "0.4.6",
+            "watchpack": "1.4.0",
+            "webpack-sources": "1.0.1",
+            "yargs": "8.0.2"
+          }
+        },
+        "webpack-dev-server": {
+          "version": "2.7.1",
+          "resolved": "http://registry.npm.taobao.org/webpack-dev-server/download/webpack-dev-server-2.7.1.tgz",
+          "integrity": "sha1-IVgPWgjNBlxxFEz29hw0W8pZqLg=",
+          "dev": true,
+          "requires": {
+            "ansi-html": "0.0.7",
+            "bonjour": "3.5.0",
+            "chokidar": "1.7.0",
+            "compression": "1.7.0",
+            "connect-history-api-fallback": "1.3.0",
+            "del": "3.0.0",
+            "express": "4.15.4",
+            "html-entities": "1.2.1",
+            "http-proxy-middleware": "0.17.4",
+            "internal-ip": "1.2.0",
+            "ip": "1.1.5",
+            "loglevel": "1.6.1",
+            "opn": "4.0.2",
+            "portfinder": "1.0.13",
+            "selfsigned": "1.10.1",
+            "serve-index": "1.9.0",
+            "sockjs": "0.3.18",
+            "sockjs-client": "1.1.4",
+            "spdy": "3.4.7",
+            "strip-ansi": "3.0.1",
+            "supports-color": "3.2.3",
+            "webpack-dev-middleware": "1.12.0",
+            "yargs": "6.6.0"
+          },
+          "dependencies": {
+            "camelcase": {
+              "version": "3.0.0",
+              "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-3.0.0.tgz",
+              "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+              "dev": true
+            },
+            "find-up": {
+              "version": "1.1.2",
+              "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz",
+              "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+              "dev": true,
+              "requires": {
+                "path-exists": "2.1.0",
+                "pinkie-promise": "2.0.1"
+              }
+            },
+            "has-flag": {
+              "version": "1.0.0",
+              "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-1.0.0.tgz",
+              "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+              "dev": true
+            },
+            "load-json-file": {
+              "version": "1.1.0",
+              "resolved": "http://registry.npm.taobao.org/load-json-file/download/load-json-file-1.1.0.tgz",
+              "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+              "dev": true,
+              "requires": {
+                "graceful-fs": "4.1.11",
+                "parse-json": "2.2.0",
+                "pify": "2.3.0",
+                "pinkie-promise": "2.0.1",
+                "strip-bom": "2.0.0"
+              }
+            },
+            "opn": {
+              "version": "4.0.2",
+              "resolved": "http://registry.npm.taobao.org/opn/download/opn-4.0.2.tgz",
+              "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=",
+              "dev": true,
+              "requires": {
+                "object-assign": "4.1.1",
+                "pinkie-promise": "2.0.1"
+              }
+            },
+            "os-locale": {
+              "version": "1.4.0",
+              "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-1.4.0.tgz",
+              "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+              "dev": true,
+              "requires": {
+                "lcid": "1.0.0"
+              }
+            },
+            "path-type": {
+              "version": "1.1.0",
+              "resolved": "http://registry.npm.taobao.org/path-type/download/path-type-1.1.0.tgz",
+              "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+              "dev": true,
+              "requires": {
+                "graceful-fs": "4.1.11",
+                "pify": "2.3.0",
+                "pinkie-promise": "2.0.1"
+              }
+            },
+            "read-pkg": {
+              "version": "1.1.0",
+              "resolved": "http://registry.npm.taobao.org/read-pkg/download/read-pkg-1.1.0.tgz",
+              "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+              "dev": true,
+              "requires": {
+                "load-json-file": "1.1.0",
+                "normalize-package-data": "2.4.0",
+                "path-type": "1.1.0"
+              }
+            },
+            "read-pkg-up": {
+              "version": "1.0.1",
+              "resolved": "http://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-1.0.1.tgz",
+              "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+              "dev": true,
+              "requires": {
+                "find-up": "1.1.2",
+                "read-pkg": "1.1.0"
+              }
+            },
+            "string-width": {
+              "version": "1.0.2",
+              "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz",
+              "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+              "dev": true,
+              "requires": {
+                "code-point-at": "1.1.0",
+                "is-fullwidth-code-point": "1.0.0",
+                "strip-ansi": "3.0.1"
+              }
+            },
+            "strip-bom": {
+              "version": "2.0.0",
+              "resolved": "http://registry.npm.taobao.org/strip-bom/download/strip-bom-2.0.0.tgz",
+              "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+              "dev": true,
+              "requires": {
+                "is-utf8": "0.2.1"
+              }
+            },
+            "supports-color": {
+              "version": "3.2.3",
+              "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-3.2.3.tgz",
+              "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+              "dev": true,
+              "requires": {
+                "has-flag": "1.0.0"
+              }
+            },
+            "which-module": {
+              "version": "1.0.0",
+              "resolved": "http://registry.npm.taobao.org/which-module/download/which-module-1.0.0.tgz",
+              "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
+              "dev": true
+            },
+            "yargs": {
+              "version": "6.6.0",
+              "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-6.6.0.tgz",
+              "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
+              "dev": true,
+              "requires": {
+                "camelcase": "3.0.0",
+                "cliui": "3.2.0",
+                "decamelize": "1.2.0",
+                "get-caller-file": "1.0.2",
+                "os-locale": "1.4.0",
+                "read-pkg-up": "1.0.1",
+                "require-directory": "2.1.1",
+                "require-main-filename": "1.0.1",
+                "set-blocking": "2.0.0",
+                "string-width": "1.0.2",
+                "which-module": "1.0.0",
+                "y18n": "3.2.1",
+                "yargs-parser": "4.2.1"
+              }
+            },
+            "yargs-parser": {
+              "version": "4.2.1",
+              "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-4.2.1.tgz",
+              "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
+              "dev": true,
+              "requires": {
+                "camelcase": "3.0.0"
+              }
+            }
+          }
+        },
+        "which-module": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz",
+          "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+          "dev": true
+        },
+        "yargs": {
+          "version": "8.0.2",
+          "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-8.0.2.tgz",
+          "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
+          "dev": true,
+          "requires": {
+            "camelcase": "4.1.0",
+            "cliui": "3.2.0",
+            "decamelize": "1.2.0",
+            "get-caller-file": "1.0.2",
+            "os-locale": "2.1.0",
+            "read-pkg-up": "2.0.0",
+            "require-directory": "2.1.1",
+            "require-main-filename": "1.0.1",
+            "set-blocking": "2.0.0",
+            "string-width": "2.1.1",
+            "which-module": "2.0.0",
+            "y18n": "3.2.1",
+            "yargs-parser": "7.0.0"
+          }
+        },
+        "yargs-parser": {
+          "version": "7.0.0",
+          "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-7.0.0.tgz",
+          "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
+          "dev": true,
+          "requires": {
+            "camelcase": "4.1.0"
+          }
+        }
       }
     },
     "@angular/common": {
       "integrity": "sha1-w6DFRNYjkqzCgTpCyKDcb1j4aSI=",
       "dev": true
     },
-    "@ngtools/webpack": {
-      "version": "1.6.1",
-      "resolved": "http://registry.npm.taobao.org/@ngtools/webpack/download/@ngtools/webpack-1.6.1.tgz",
-      "integrity": "sha1-JH+neTep3yOnzEmf7jBbywV0Wxg=",
-      "dev": true,
-      "requires": {
-        "loader-utils": "1.1.0",
-        "magic-string": "0.22.4",
-        "source-map": "0.5.6"
-      }
-    },
     "@ngx-translate/core": {
-      "version": "7.2.2",
-      "resolved": "http://registry.npm.taobao.org/@ngx-translate/core/download/@ngx-translate/core-7.2.2.tgz",
-      "integrity": "sha1-5wBp1e+Og36jNuaJB3N4b177XeU="
+      "version": "8.0.0",
+      "resolved": "http://registry.npm.taobao.org/@ngx-translate/core/download/@ngx-translate/core-8.0.0.tgz",
+      "integrity": "sha1-dR/WtRLYDzp0jS3o38lt/vopr+A="
     },
     "@ngx-translate/http-loader": {
       "version": "1.1.0",
       "resolved": "http://registry.npm.taobao.org/@ngx-translate/http-loader/download/@ngx-translate/http-loader-1.1.0.tgz",
       "integrity": "sha1-opMmDOpvYXhKb/nFWklz6pd43OI="
     },
+    "@schematics/angular": {
+      "version": "0.0.49",
+      "resolved": "http://registry.npm.taobao.org/@schematics/angular/download/@schematics/angular-0.0.49.tgz",
+      "integrity": "sha1-wAylc3VtannuUYsF6rX+bntz80E=",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/core": "0.0.20"
+      }
+    },
     "@types/jasmine": {
       "version": "2.5.53",
       "resolved": "http://registry.npm.taobao.org/@types/jasmine/download/@types/jasmine-2.5.53.tgz",
       "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
       "dev": true
     },
-    "angular-in-memory-web-api": {
-      "version": "0.3.2",
-      "resolved": "http://10.75.8.148/repository/npm-pub/angular-in-memory-web-api/-/angular-in-memory-web-api-0.3.2.tgz",
-      "integrity": "sha1-iDbZ4lNNN7co88taHK9v4ef7vs0="
-    },
-    "ansi-escapes": {
-      "version": "2.0.0",
-      "resolved": "http://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-2.0.0.tgz",
-      "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=",
-      "dev": true
-    },
     "ansi-html": {
       "version": "0.0.7",
       "resolved": "http://registry.npm.taobao.org/ansi-html/download/ansi-html-0.0.7.tgz",
         }
       }
     },
+    "buffer-from": {
+      "version": "1.0.0",
+      "resolved": "http://registry.npm.taobao.org/buffer-from/download/buffer-from-1.0.0.tgz",
+      "integrity": "sha1-TLiDLSNhJYmwQG6eKVbBfwb99TE=",
+      "dev": true
+    },
     "buffer-indexof": {
       "version": "1.1.0",
       "resolved": "http://registry.npm.taobao.org/buffer-indexof/download/buffer-indexof-1.1.0.tgz",
       "integrity": "sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=",
       "dev": true
     },
+    "cacache": {
+      "version": "10.0.4",
+      "resolved": "http://registry.npm.taobao.org/cacache/download/cacache-10.0.4.tgz",
+      "integrity": "sha1-ZFI2eZnv+dQYiu/ZoU6dfGomNGA=",
+      "dev": true,
+      "requires": {
+        "bluebird": "3.5.1",
+        "chownr": "1.0.1",
+        "glob": "7.1.2",
+        "graceful-fs": "4.1.11",
+        "lru-cache": "4.1.1",
+        "mississippi": "2.0.0",
+        "mkdirp": "0.5.1",
+        "move-concurrently": "1.0.1",
+        "promise-inflight": "1.0.1",
+        "rimraf": "2.6.2",
+        "ssri": "5.3.0",
+        "unique-filename": "1.1.0",
+        "y18n": "4.0.0"
+      },
+      "dependencies": {
+        "bluebird": {
+          "version": "3.5.1",
+          "resolved": "http://registry.npm.taobao.org/bluebird/download/bluebird-3.5.1.tgz",
+          "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=",
+          "dev": true
+        },
+        "rimraf": {
+          "version": "2.6.2",
+          "resolved": "http://registry.npm.taobao.org/rimraf/download/rimraf-2.6.2.tgz",
+          "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
+          "dev": true,
+          "requires": {
+            "glob": "7.1.2"
+          }
+        },
+        "y18n": {
+          "version": "4.0.0",
+          "resolved": "http://registry.npm.taobao.org/y18n/download/y18n-4.0.0.tgz",
+          "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=",
+          "dev": true
+        }
+      }
+    },
     "callsite": {
       "version": "1.0.0",
       "resolved": "http://registry.npm.taobao.org/callsite/download/callsite-1.0.0.tgz",
         }
       }
     },
+    "charenc": {
+      "version": "0.0.2",
+      "resolved": "http://registry.npm.taobao.org/charenc/download/charenc-0.0.2.tgz",
+      "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=",
+      "dev": true
+    },
     "chokidar": {
       "version": "1.7.0",
       "resolved": "http://registry.npm.taobao.org/chokidar/download/chokidar-1.7.0.tgz",
         "readdirp": "2.1.0"
       }
     },
+    "chownr": {
+      "version": "1.0.1",
+      "resolved": "http://registry.npm.taobao.org/chownr/download/chownr-1.0.1.tgz",
+      "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
+      "dev": true
+    },
     "cipher-base": {
       "version": "1.0.4",
       "resolved": "http://registry.npm.taobao.org/cipher-base/download/cipher-base-1.0.4.tgz",
         "source-map": "0.5.6"
       }
     },
-    "cli-cursor": {
-      "version": "2.1.0",
-      "resolved": "http://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz",
-      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
-      "dev": true,
-      "requires": {
-        "restore-cursor": "2.0.0"
-      }
-    },
-    "cli-width": {
-      "version": "2.1.0",
-      "resolved": "http://registry.npm.taobao.org/cli-width/download/cli-width-2.1.0.tgz",
-      "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=",
-      "dev": true
-    },
     "cliui": {
       "version": "3.2.0",
       "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-3.2.0.tgz",
         "babel-runtime": "6.26.0"
       }
     },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "http://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "dev": true
+    },
     "component-bind": {
       "version": "1.0.0",
       "resolved": "http://registry.npm.taobao.org/component-bind/download/component-bind-1.0.0.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "dev": true
     },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "http://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz",
+      "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=",
+      "dev": true,
+      "requires": {
+        "buffer-from": "1.0.0",
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5",
+        "typedarray": "0.0.6"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
+          "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.5",
+          "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz",
+          "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "2.0.0",
+            "safe-buffer": "5.1.1",
+            "string_decoder": "1.0.3",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.3",
+          "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz",
+          "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "5.1.1"
+          }
+        }
+      }
+    },
     "connect": {
       "version": "3.6.3",
       "resolved": "http://registry.npm.taobao.org/connect/download/connect-3.6.3.tgz",
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
       "dev": true
     },
+    "copy-concurrently": {
+      "version": "1.0.5",
+      "resolved": "http://registry.npm.taobao.org/copy-concurrently/download/copy-concurrently-1.0.5.tgz",
+      "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=",
+      "dev": true,
+      "requires": {
+        "aproba": "1.1.2",
+        "fs-write-stream-atomic": "1.0.10",
+        "iferr": "0.1.5",
+        "mkdirp": "0.5.1",
+        "rimraf": "2.6.1",
+        "run-queue": "1.0.3"
+      }
+    },
+    "copy-webpack-plugin": {
+      "version": "4.5.1",
+      "resolved": "http://registry.npm.taobao.org/copy-webpack-plugin/download/copy-webpack-plugin-4.5.1.tgz",
+      "integrity": "sha1-/E9o9K3YN8xeE9ERsgcVeTIl0pw=",
+      "dev": true,
+      "requires": {
+        "cacache": "10.0.4",
+        "find-cache-dir": "1.0.0",
+        "globby": "7.1.1",
+        "is-glob": "4.0.0",
+        "loader-utils": "1.1.0",
+        "minimatch": "3.0.4",
+        "p-limit": "1.1.0",
+        "serialize-javascript": "1.4.0"
+      },
+      "dependencies": {
+        "globby": {
+          "version": "7.1.1",
+          "resolved": "http://registry.npm.taobao.org/globby/download/globby-7.1.1.tgz",
+          "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+          "dev": true,
+          "requires": {
+            "array-union": "1.0.2",
+            "dir-glob": "2.0.0",
+            "glob": "7.1.2",
+            "ignore": "3.3.7",
+            "pify": "3.0.0",
+            "slash": "1.0.0"
+          }
+        },
+        "is-extglob": {
+          "version": "2.1.1",
+          "resolved": "http://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
+          "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+          "dev": true
+        },
+        "is-glob": {
+          "version": "4.0.0",
+          "resolved": "http://registry.npm.taobao.org/is-glob/download/is-glob-4.0.0.tgz",
+          "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "2.1.1"
+          }
+        },
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "http://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        }
+      }
+    },
     "core-js": {
       "version": "2.5.0",
       "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-2.5.0.tgz",
         "which": "1.3.0"
       }
     },
+    "crypt": {
+      "version": "0.0.2",
+      "resolved": "http://registry.npm.taobao.org/crypt/download/crypt-0.0.2.tgz",
+      "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=",
+      "dev": true
+    },
     "cryptiles": {
       "version": "2.0.5",
       "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-2.0.5.tgz",
       "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
       "dev": true
     },
+    "cyclist": {
+      "version": "0.2.2",
+      "resolved": "http://registry.npm.taobao.org/cyclist/download/cyclist-0.2.2.tgz",
+      "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
+      "dev": true
+    },
     "d": {
       "version": "1.0.0",
       "resolved": "http://registry.npm.taobao.org/d/download/d-1.0.0.tgz",
         "randombytes": "2.0.5"
       }
     },
+    "dir-glob": {
+      "version": "2.0.0",
+      "resolved": "http://registry.npm.taobao.org/dir-glob/download/dir-glob-2.0.0.tgz",
+      "integrity": "sha1-CyBdK2rvmCOMooZZioIE0p0KADQ=",
+      "dev": true,
+      "requires": {
+        "arrify": "1.0.1",
+        "path-type": "3.0.0"
+      },
+      "dependencies": {
+        "path-type": {
+          "version": "3.0.0",
+          "resolved": "http://registry.npm.taobao.org/path-type/download/path-type-3.0.0.tgz",
+          "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=",
+          "dev": true,
+          "requires": {
+            "pify": "3.0.0"
+          }
+        },
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "http://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        }
+      }
+    },
     "directory-encoder": {
       "version": "0.7.2",
       "resolved": "http://registry.npm.taobao.org/directory-encoder/download/directory-encoder-0.7.2.tgz",
         "domelementtype": "1.3.0"
       }
     },
+    "duplexify": {
+      "version": "3.5.4",
+      "resolved": "http://registry.npm.taobao.org/duplexify/download/duplexify-3.5.4.tgz",
+      "integrity": "sha1-S7RsF5bqvr7sTKmi5muAjLej2LQ=",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "1.4.1",
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5",
+        "stream-shift": "1.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
+          "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.5",
+          "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz",
+          "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "2.0.0",
+            "safe-buffer": "5.1.1",
+            "string_decoder": "1.0.3",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.3",
+          "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz",
+          "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "5.1.1"
+          }
+        }
+      }
+    },
     "ecc-jsbn": {
       "version": "0.1.1",
       "resolved": "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.1.tgz",
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
       "dev": true
     },
+    "ejs": {
+      "version": "2.5.8",
+      "resolved": "http://registry.npm.taobao.org/ejs/download/ejs-2.5.8.tgz",
+      "integrity": "sha1-KraVRhnyJeYZO3rF98OcSP7+Q4A=",
+      "dev": true
+    },
     "electron-to-chromium": {
       "version": "1.3.18",
       "resolved": "http://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.18.tgz",
         "minimalistic-crypto-utils": "1.0.1"
       }
     },
-    "ember-cli-normalize-entity-name": {
-      "version": "1.0.0",
-      "resolved": "http://registry.npm.taobao.org/ember-cli-normalize-entity-name/download/ember-cli-normalize-entity-name-1.0.0.tgz",
-      "integrity": "sha1-CxT3vLxZmqEXtf3cgeT9A8S61bc=",
-      "dev": true,
-      "requires": {
-        "silent-error": "1.1.0"
-      }
-    },
     "ember-cli-string-utils": {
       "version": "1.1.0",
       "resolved": "http://registry.npm.taobao.org/ember-cli-string-utils/download/ember-cli-string-utils-1.1.0.tgz",
       "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=",
       "dev": true
     },
+    "end-of-stream": {
+      "version": "1.4.1",
+      "resolved": "http://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.1.tgz",
+      "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=",
+      "dev": true,
+      "requires": {
+        "once": "1.4.0"
+      }
+    },
     "engine.io": {
       "version": "1.8.3",
       "resolved": "http://registry.npm.taobao.org/engine.io/download/engine.io-1.8.3.tgz",
         "tapable": "0.2.8"
       }
     },
-    "ensure-posix-path": {
-      "version": "1.0.2",
-      "resolved": "http://registry.npm.taobao.org/ensure-posix-path/download/ensure-posix-path-1.0.2.tgz",
-      "integrity": "sha1-pls+QtC3HPxYXrd0+ZQ8jZuRsMI=",
-      "dev": true
-    },
     "ent": {
       "version": "2.2.0",
       "resolved": "http://registry.npm.taobao.org/ent/download/ent-2.2.0.tgz",
       "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
       "dev": true
     },
-    "external-editor": {
-      "version": "2.0.4",
-      "resolved": "http://registry.npm.taobao.org/external-editor/download/external-editor-2.0.4.tgz",
-      "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=",
-      "dev": true,
-      "requires": {
-        "iconv-lite": "0.4.18",
-        "jschardet": "1.5.1",
-        "tmp": "0.0.31"
-      }
-    },
     "extglob": {
       "version": "0.3.2",
       "resolved": "http://registry.npm.taobao.org/extglob/download/extglob-0.3.2.tgz",
         "websocket-driver": "0.6.5"
       }
     },
-    "figures": {
-      "version": "2.0.0",
-      "resolved": "http://registry.npm.taobao.org/figures/download/figures-2.0.0.tgz",
-      "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
-      "dev": true,
-      "requires": {
-        "escape-string-regexp": "1.0.5"
-      }
-    },
     "file-loader": {
       "version": "0.10.1",
       "resolved": "http://registry.npm.taobao.org/file-loader/download/file-loader-0.10.1.tgz",
         "unpipe": "1.0.0"
       }
     },
+    "find-cache-dir": {
+      "version": "1.0.0",
+      "resolved": "http://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-1.0.0.tgz",
+      "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+      "dev": true,
+      "requires": {
+        "commondir": "1.0.1",
+        "make-dir": "1.2.0",
+        "pkg-dir": "2.0.0"
+      }
+    },
     "find-up": {
       "version": "1.1.2",
       "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz",
       "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
       "dev": true
     },
+    "flush-write-stream": {
+      "version": "1.0.3",
+      "resolved": "http://registry.npm.taobao.org/flush-write-stream/download/flush-write-stream-1.0.3.tgz",
+      "integrity": "sha1-xdWG7zivYJdlC0m8QbVfq7GfNb0=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
+          "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.5",
+          "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz",
+          "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "2.0.0",
+            "safe-buffer": "5.1.1",
+            "string_decoder": "1.0.3",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.3",
+          "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz",
+          "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "5.1.1"
+          }
+        }
+      }
+    },
     "font-awesome": {
       "version": "4.7.0",
       "resolved": "http://10.75.8.148/repository/npm-pub/font-awesome/-/font-awesome-4.7.0.tgz",
       "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=",
       "dev": true
     },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "http://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz",
+      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
+          "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.5",
+          "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz",
+          "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "2.0.0",
+            "safe-buffer": "5.1.1",
+            "string_decoder": "1.0.3",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.3",
+          "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz",
+          "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "5.1.1"
+          }
+        }
+      }
+    },
     "fs-access": {
       "version": "1.0.1",
       "resolved": "http://registry.npm.taobao.org/fs-access/download/fs-access-1.0.1.tgz",
         "universalify": "0.1.1"
       }
     },
+    "fs-write-stream-atomic": {
+      "version": "1.0.10",
+      "resolved": "http://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz",
+      "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "4.1.11",
+        "iferr": "0.1.5",
+        "imurmurhash": "0.1.4",
+        "readable-stream": "1.0.34"
+      }
+    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz",
         "extend": "3.0.1"
       }
     },
-    "iconv-lite": {
-      "version": "0.4.18",
-      "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.18.tgz",
-      "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=",
-      "dev": true
-    },
     "icss-replace-symbols": {
       "version": "1.1.0",
       "resolved": "http://registry.npm.taobao.org/icss-replace-symbols/download/icss-replace-symbols-1.1.0.tgz",
       "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=",
       "dev": true
     },
+    "iferr": {
+      "version": "0.1.5",
+      "resolved": "http://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz",
+      "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+      "dev": true
+    },
+    "ignore": {
+      "version": "3.3.7",
+      "resolved": "http://registry.npm.taobao.org/ignore/download/ignore-3.3.7.tgz",
+      "integrity": "sha1-YSKJv7PCIOGGpYEYYY1b6MG6sCE=",
+      "dev": true
+    },
     "image-size": {
       "version": "0.5.5",
       "resolved": "http://registry.npm.taobao.org/image-size/download/image-size-0.5.5.tgz",
         "xmldom": "0.1.27"
       }
     },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "http://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
     "in-publish": {
       "version": "2.0.0",
       "resolved": "http://registry.npm.taobao.org/in-publish/download/in-publish-2.0.0.tgz",
       "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
       "dev": true
     },
-    "inflection": {
-      "version": "1.12.0",
-      "resolved": "http://registry.npm.taobao.org/inflection/download/inflection-1.12.0.tgz",
-      "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=",
-      "dev": true
-    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz",
       "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
       "dev": true
     },
-    "inquirer": {
-      "version": "3.2.2",
-      "resolved": "http://registry.npm.taobao.org/inquirer/download/inquirer-3.2.2.tgz",
-      "integrity": "sha1-wqrt4VB8xU2CaBhzd0LWIb7y6CM=",
-      "dev": true,
-      "requires": {
-        "ansi-escapes": "2.0.0",
-        "chalk": "2.1.0",
-        "cli-cursor": "2.1.0",
-        "cli-width": "2.1.0",
-        "external-editor": "2.0.4",
-        "figures": "2.0.0",
-        "lodash": "4.17.4",
-        "mute-stream": "0.0.7",
-        "run-async": "2.3.0",
-        "rx-lite": "4.0.8",
-        "rx-lite-aggregates": "4.0.8",
-        "string-width": "2.1.1",
-        "strip-ansi": "4.0.0",
-        "through": "2.3.8"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "strip-ansi": {
-          "version": "4.0.0",
-          "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz",
-          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "3.0.0"
-          }
-        }
-      }
-    },
     "internal-ip": {
       "version": "1.2.0",
       "resolved": "http://registry.npm.taobao.org/internal-ip/download/internal-ip-1.2.0.tgz",
       "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
       "dev": true
     },
-    "is-promise": {
-      "version": "2.1.0",
-      "resolved": "http://registry.npm.taobao.org/is-promise/download/is-promise-2.1.0.tgz",
-      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
-      "dev": true
-    },
     "is-stream": {
       "version": "1.1.0",
       "resolved": "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz",
       "dev": true,
       "optional": true
     },
-    "jschardet": {
-      "version": "1.5.1",
-      "resolved": "http://registry.npm.taobao.org/jschardet/download/jschardet-1.5.1.tgz",
-      "integrity": "sha1-xRn2KfhrOlvtuliojTETCe7Al/k=",
-      "dev": true
-    },
     "jsesc": {
       "version": "0.5.0",
       "resolved": "http://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz",
       "dev": true
     },
     "jsplumb": {
-      "version": "2.5.0",
-      "resolved": "http://registry.npm.taobao.org/jsplumb/download/jsplumb-2.5.0.tgz",
-      "integrity": "sha1-5gLBaEKKcYiYr6Kmm8lmldlhjiQ="
+      "version": "2.5.1",
+      "resolved": "http://registry.npm.taobao.org/jsplumb/download/jsplumb-2.5.1.tgz",
+      "integrity": "sha1-PMVAJJhdzJHSeUOARSJkH/qu3L4="
     },
     "jsprim": {
       "version": "1.4.1",
         }
       }
     },
-    "license-webpack-plugin": {
-      "version": "0.5.1",
-      "resolved": "http://registry.npm.taobao.org/license-webpack-plugin/download/license-webpack-plugin-0.5.1.tgz",
-      "integrity": "sha1-aNivEDSGqcTrzt237V071h84O+Q=",
-      "dev": true,
-      "requires": {
-        "object-assign": "4.1.1"
-      }
-    },
     "load-json-file": {
       "version": "1.1.0",
       "resolved": "http://registry.npm.taobao.org/load-json-file/download/load-json-file-1.1.0.tgz",
         }
       }
     },
+    "loglevel": {
+      "version": "1.6.1",
+      "resolved": "http://registry.npm.taobao.org/loglevel/download/loglevel-1.6.1.tgz",
+      "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
+      "dev": true
+    },
     "longest": {
       "version": "1.0.1",
       "resolved": "http://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz",
         "vlq": "0.2.2"
       }
     },
+    "make-dir": {
+      "version": "1.2.0",
+      "resolved": "http://registry.npm.taobao.org/make-dir/download/make-dir-1.2.0.tgz",
+      "integrity": "sha1-bWpJ7q1KrilsU7vzoaAIvWyJRps=",
+      "dev": true,
+      "requires": {
+        "pify": "3.0.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "http://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        }
+      }
+    },
     "make-error": {
       "version": "1.3.0",
       "resolved": "http://registry.npm.taobao.org/make-error/download/make-error-1.3.0.tgz",
       "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
       "dev": true
     },
-    "matcher-collection": {
-      "version": "1.0.4",
-      "resolved": "http://registry.npm.taobao.org/matcher-collection/download/matcher-collection-1.0.4.tgz",
-      "integrity": "sha1-L2auCGmZbynkPQtiyD3R1D5YF1U=",
-      "dev": true,
-      "requires": {
-        "minimatch": "3.0.4"
-      }
-    },
     "math-expression-evaluator": {
       "version": "1.2.17",
       "resolved": "http://registry.npm.taobao.org/math-expression-evaluator/download/math-expression-evaluator-1.2.17.tgz",
       "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=",
       "dev": true
     },
+    "md5": {
+      "version": "2.2.1",
+      "resolved": "http://registry.npm.taobao.org/md5/download/md5-2.2.1.tgz",
+      "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=",
+      "dev": true,
+      "requires": {
+        "charenc": "0.0.2",
+        "crypt": "0.0.2",
+        "is-buffer": "1.1.5"
+      }
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "http://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
       "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
       "dev": true
     },
+    "mississippi": {
+      "version": "2.0.0",
+      "resolved": "http://registry.npm.taobao.org/mississippi/download/mississippi-2.0.0.tgz",
+      "integrity": "sha1-NEKlCPr8KFAEhv7qmUCWduTuWm8=",
+      "dev": true,
+      "requires": {
+        "concat-stream": "1.6.2",
+        "duplexify": "3.5.4",
+        "end-of-stream": "1.4.1",
+        "flush-write-stream": "1.0.3",
+        "from2": "2.3.0",
+        "parallel-transform": "1.1.0",
+        "pump": "2.0.1",
+        "pumpify": "1.4.0",
+        "stream-each": "1.2.2",
+        "through2": "2.0.3"
+      }
+    },
     "mixin-object": {
       "version": "2.0.1",
       "resolved": "http://registry.npm.taobao.org/mixin-object/download/mixin-object-2.0.1.tgz",
         "minimist": "0.0.8"
       }
     },
+    "move-concurrently": {
+      "version": "1.0.1",
+      "resolved": "http://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
+      "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+      "dev": true,
+      "requires": {
+        "aproba": "1.1.2",
+        "copy-concurrently": "1.0.5",
+        "fs-write-stream-atomic": "1.0.10",
+        "mkdirp": "0.5.1",
+        "rimraf": "2.6.1",
+        "run-queue": "1.0.3"
+      }
+    },
     "ms": {
       "version": "2.0.0",
       "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
       "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
       "dev": true
     },
-    "mute-stream": {
-      "version": "0.0.7",
-      "resolved": "http://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.7.tgz",
-      "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
-      "dev": true
-    },
     "nan": {
       "version": "2.6.2",
       "resolved": "http://registry.npm.taobao.org/nan/download/nan-2.6.2.tgz",
       "integrity": "sha1-Ce0G2Qj187sj+CGg+0UumhfXZls="
     },
     "ngx-tree-select": {
-      "version": "0.11.1",
-      "resolved": "http://10.75.8.148/repository/npm-pub/ngx-tree-select/-/ngx-tree-select-0.11.1.tgz",
-      "integrity": "sha1-r2hQgxyUPZDznDotDvIpYh7DH5M="
+      "version": "0.13.3",
+      "resolved": "http://registry.npm.taobao.org/ngx-tree-select/download/ngx-tree-select-0.13.3.tgz",
+      "integrity": "sha1-OZp+fOF8JwYJdIhxmNMUZy3h4Rw="
     },
     "no-case": {
       "version": "2.3.1",
         "wrappy": "1.0.2"
       }
     },
-    "onetime": {
-      "version": "2.0.1",
-      "resolved": "http://registry.npm.taobao.org/onetime/download/onetime-2.0.1.tgz",
-      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
-      "dev": true,
-      "requires": {
-        "mimic-fn": "1.1.0"
-      }
-    },
     "opn": {
       "version": "5.1.0",
       "resolved": "http://registry.npm.taobao.org/opn/download/opn-5.1.0.tgz",
       "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-1.4.0.tgz",
       "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
       "dev": true,
+      "optional": true,
       "requires": {
         "lcid": "1.0.0"
       }
       "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
       "dev": true
     },
+    "parallel-transform": {
+      "version": "1.1.0",
+      "resolved": "http://registry.npm.taobao.org/parallel-transform/download/parallel-transform-1.1.0.tgz",
+      "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+      "dev": true,
+      "requires": {
+        "cyclist": "0.2.2",
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
+          "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.5",
+          "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz",
+          "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "2.0.0",
+            "safe-buffer": "5.1.1",
+            "string_decoder": "1.0.3",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.3",
+          "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz",
+          "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "5.1.1"
+          }
+        }
+      }
+    },
     "param-case": {
       "version": "2.1.1",
       "resolved": "http://registry.npm.taobao.org/param-case/download/param-case-2.1.1.tgz",
         "pinkie": "2.0.4"
       }
     },
+    "pkg-dir": {
+      "version": "2.0.0",
+      "resolved": "http://registry.npm.taobao.org/pkg-dir/download/pkg-dir-2.0.0.tgz",
+      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+      "dev": true,
+      "requires": {
+        "find-up": "2.1.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "2.1.0",
+          "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz",
+          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+          "dev": true,
+          "requires": {
+            "locate-path": "2.0.0"
+          }
+        }
+      }
+    },
     "portfinder": {
       "version": "1.0.13",
       "resolved": "http://registry.npm.taobao.org/portfinder/download/portfinder-1.0.13.tgz",
       }
     },
     "primeng": {
-      "version": "4.2.0-rc.1",
-      "resolved": "http://10.75.8.148/repository/npm-pub/primeng/-/primeng-4.2.0-rc.1.tgz",
-      "integrity": "sha1-Vzo8fvKbx6v3ywconsOa6xpTE28="
+      "version": "4.3.0",
+      "resolved": "http://registry.npm.taobao.org/primeng/download/primeng-4.3.0.tgz",
+      "integrity": "sha1-aH7NHhoVjPDodC78fam5M4zUcMM="
     },
     "process": {
       "version": "0.11.10",
         "asap": "2.0.6"
       }
     },
+    "promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "http://registry.npm.taobao.org/promise-inflight/download/promise-inflight-1.0.1.tgz",
+      "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+      "dev": true
+    },
     "protractor": {
       "version": "5.1.2",
       "resolved": "http://registry.npm.taobao.org/protractor/download/protractor-5.1.2.tgz",
         "randombytes": "2.0.5"
       }
     },
+    "pump": {
+      "version": "2.0.1",
+      "resolved": "http://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz",
+      "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "1.4.1",
+        "once": "1.4.0"
+      }
+    },
+    "pumpify": {
+      "version": "1.4.0",
+      "resolved": "http://registry.npm.taobao.org/pumpify/download/pumpify-1.4.0.tgz",
+      "integrity": "sha1-gLfF334kFT0D8OesigWl0Gi9B/s=",
+      "dev": true,
+      "requires": {
+        "duplexify": "3.5.4",
+        "inherits": "2.0.3",
+        "pump": "2.0.1"
+      }
+    },
     "punycode": {
       "version": "1.4.1",
       "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz",
         "path-parse": "1.0.5"
       }
     },
-    "restore-cursor": {
-      "version": "2.0.0",
-      "resolved": "http://registry.npm.taobao.org/restore-cursor/download/restore-cursor-2.0.0.tgz",
-      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
-      "dev": true,
-      "requires": {
-        "onetime": "2.0.1",
-        "signal-exit": "3.0.2"
-      }
-    },
     "right-align": {
       "version": "0.1.3",
       "resolved": "http://registry.npm.taobao.org/right-align/download/right-align-0.1.3.tgz",
         "inherits": "2.0.3"
       }
     },
-    "rsvp": {
-      "version": "3.6.2",
-      "resolved": "http://registry.npm.taobao.org/rsvp/download/rsvp-3.6.2.tgz",
-      "integrity": "sha1-LpZJFZmpbN4bUV1WdKj3qRRSkmo=",
-      "dev": true
-    },
-    "run-async": {
-      "version": "2.3.0",
-      "resolved": "http://registry.npm.taobao.org/run-async/download/run-async-2.3.0.tgz",
-      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
-      "dev": true,
-      "requires": {
-        "is-promise": "2.1.0"
-      }
-    },
-    "rx-lite": {
-      "version": "4.0.8",
-      "resolved": "http://registry.npm.taobao.org/rx-lite/download/rx-lite-4.0.8.tgz",
-      "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
-      "dev": true
-    },
-    "rx-lite-aggregates": {
-      "version": "4.0.8",
-      "resolved": "http://registry.npm.taobao.org/rx-lite-aggregates/download/rx-lite-aggregates-4.0.8.tgz",
-      "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+    "run-queue": {
+      "version": "1.0.3",
+      "resolved": "http://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz",
+      "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
       "dev": true,
       "requires": {
-        "rx-lite": "4.0.8"
+        "aproba": "1.1.2"
       }
     },
     "rxjs": {
         "ajv": "5.2.2"
       }
     },
-    "script-loader": {
-      "version": "0.7.0",
-      "resolved": "http://registry.npm.taobao.org/script-loader/download/script-loader-0.7.0.tgz",
-      "integrity": "sha1-aF3H5waeDe56kmdPDrxbD1W6pew=",
-      "dev": true,
-      "requires": {
-        "raw-loader": "0.5.1"
-      }
-    },
     "scss-tokenizer": {
       "version": "0.2.3",
       "resolved": "http://registry.npm.taobao.org/scss-tokenizer/download/scss-tokenizer-0.2.3.tgz",
         }
       }
     },
+    "serialize-javascript": {
+      "version": "1.4.0",
+      "resolved": "http://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-1.4.0.tgz",
+      "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=",
+      "dev": true
+    },
     "serve-index": {
       "version": "1.9.0",
       "resolved": "http://registry.npm.taobao.org/serve-index/download/serve-index-1.9.0.tgz",
         "debug": "2.6.8"
       }
     },
+    "slash": {
+      "version": "1.0.0",
+      "resolved": "http://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz",
+      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+      "dev": true
+    },
     "sntp": {
       "version": "1.0.9",
       "resolved": "http://registry.npm.taobao.org/sntp/download/sntp-1.0.9.tgz",
         }
       }
     },
-    "sockjs-client": {
-      "version": "1.1.2",
-      "resolved": "http://registry.npm.taobao.org/sockjs-client/download/sockjs-client-1.1.2.tgz",
-      "integrity": "sha1-8CEqhVDkyUaMjM6u79LjSTwDOtU=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.8",
-        "eventsource": "0.1.6",
-        "faye-websocket": "0.11.1",
-        "inherits": "2.0.3",
-        "json3": "3.3.2",
-        "url-parse": "1.1.9"
-      },
-      "dependencies": {
-        "faye-websocket": {
-          "version": "0.11.1",
-          "resolved": "http://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.11.1.tgz",
-          "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
-          "dev": true,
-          "requires": {
-            "websocket-driver": "0.6.5"
-          }
-        }
-      }
-    },
     "sort-keys": {
       "version": "1.1.2",
       "resolved": "http://registry.npm.taobao.org/sort-keys/download/sort-keys-1.1.2.tgz",
         }
       }
     },
+    "ssri": {
+      "version": "5.3.0",
+      "resolved": "http://registry.npm.taobao.org/ssri/download/ssri-5.3.0.tgz",
+      "integrity": "sha1-ujhyycbTOgcEp9cf8EXl7EiZnQY=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
     "statuses": {
       "version": "1.3.1",
       "resolved": "http://registry.npm.taobao.org/statuses/download/statuses-1.3.1.tgz",
         }
       }
     },
+    "stream-each": {
+      "version": "1.2.2",
+      "resolved": "http://registry.npm.taobao.org/stream-each/download/stream-each-1.2.2.tgz",
+      "integrity": "sha1-joxGP5HaiZF3h2WHP+TZYNj2Fr0=",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "1.4.1",
+        "stream-shift": "1.0.0"
+      }
+    },
     "stream-http": {
       "version": "2.7.2",
       "resolved": "http://registry.npm.taobao.org/stream-http/download/stream-http-2.7.2.tgz",
         }
       }
     },
+    "stream-shift": {
+      "version": "1.0.0",
+      "resolved": "http://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.0.tgz",
+      "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+      "dev": true
+    },
     "strict-uri-encode": {
       "version": "1.1.0",
       "resolved": "http://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz",
         "inherits": "2.0.3"
       }
     },
-    "temp": {
-      "version": "0.8.3",
-      "resolved": "http://registry.npm.taobao.org/temp/download/temp-0.8.3.tgz",
-      "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=",
-      "dev": true,
-      "requires": {
-        "os-tmpdir": "1.0.2",
-        "rimraf": "2.2.8"
-      },
-      "dependencies": {
-        "rimraf": {
-          "version": "2.2.8",
-          "resolved": "http://registry.npm.taobao.org/rimraf/download/rimraf-2.2.8.tgz",
-          "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
-          "dev": true
-        }
-      }
-    },
     "tether": {
       "version": "1.4.0",
       "resolved": "http://10.75.8.148/repository/npm-pub/tether/-/tether-1.4.0.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
       "dev": true
     },
+    "through2": {
+      "version": "2.0.3",
+      "resolved": "http://registry.npm.taobao.org/through2/download/through2-2.0.3.tgz",
+      "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "2.3.5",
+        "xtend": "4.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
+          "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.5",
+          "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz",
+          "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=",
+          "dev": true,
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "2.0.0",
+            "safe-buffer": "5.1.1",
+            "string_decoder": "1.0.3",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "string_decoder": {
+          "version": "1.0.3",
+          "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz",
+          "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "5.1.1"
+          }
+        }
+      }
+    },
     "thunky": {
       "version": "0.1.0",
       "resolved": "http://registry.npm.taobao.org/thunky/download/thunky-0.1.0.tgz",
         "mime-types": "2.1.16"
       }
     },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "http://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+      "dev": true
+    },
     "typescript": {
-      "version": "2.3.4",
-      "resolved": "http://registry.npm.taobao.org/typescript/download/typescript-2.3.4.tgz",
-      "integrity": "sha1-PTgyGCgjHkNPKHUUlZw3qCtin0I=",
+      "version": "2.4.2",
+      "resolved": "http://registry.npm.taobao.org/typescript/download/typescript-2.4.2.tgz",
+      "integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ=",
       "dev": true
     },
     "uglify-js": {
       "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
       "dev": true
     },
+    "unique-filename": {
+      "version": "1.1.0",
+      "resolved": "http://registry.npm.taobao.org/unique-filename/download/unique-filename-1.1.0.tgz",
+      "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=",
+      "dev": true,
+      "requires": {
+        "unique-slug": "2.0.0"
+      }
+    },
+    "unique-slug": {
+      "version": "2.0.0",
+      "resolved": "http://registry.npm.taobao.org/unique-slug/download/unique-slug-2.0.0.tgz",
+      "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
+      "dev": true,
+      "requires": {
+        "imurmurhash": "0.1.4"
+      }
+    },
     "universalify": {
       "version": "0.1.1",
       "resolved": "http://registry.npm.taobao.org/universalify/download/universalify-0.1.1.tgz",
       "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
       "dev": true
     },
-    "walk-sync": {
-      "version": "0.3.2",
-      "resolved": "http://registry.npm.taobao.org/walk-sync/download/walk-sync-0.3.2.tgz",
-      "integrity": "sha1-SCcoCvxC0OA1NnxKTjHurA0Tb3U=",
-      "dev": true,
-      "requires": {
-        "ensure-posix-path": "1.0.2",
-        "matcher-collection": "1.0.4"
-      }
-    },
     "watchpack": {
       "version": "1.4.0",
       "resolved": "http://registry.npm.taobao.org/watchpack/download/watchpack-1.4.0.tgz",
         }
       }
     },
-    "webpack-dev-middleware": {
-      "version": "1.12.0",
-      "resolved": "http://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-1.12.0.tgz",
-      "integrity": "sha1-007++y7dp+HTtdvgcolRMhllFwk=",
-      "dev": true,
-      "requires": {
-        "memory-fs": "0.4.1",
-        "mime": "1.3.6",
-        "path-is-absolute": "1.0.1",
-        "range-parser": "1.2.0",
-        "time-stamp": "2.0.0"
-      }
-    },
-    "webpack-dev-server": {
-      "version": "2.5.1",
-      "resolved": "http://registry.npm.taobao.org/webpack-dev-server/download/webpack-dev-server-2.5.1.tgz",
-      "integrity": "sha1-oC5yaoe7YD211xq7fW0mSb8Qx2k=",
+    "webpack-concat-plugin": {
+      "version": "1.4.0",
+      "resolved": "http://registry.npm.taobao.org/webpack-concat-plugin/download/webpack-concat-plugin-1.4.0.tgz",
+      "integrity": "sha1-pus/AILQPHnY7i8VGMf0jkTuEsU=",
       "dev": true,
       "requires": {
-        "ansi-html": "0.0.7",
-        "bonjour": "3.5.0",
-        "chokidar": "1.7.0",
-        "compression": "1.7.0",
-        "connect-history-api-fallback": "1.3.0",
-        "del": "3.0.0",
-        "express": "4.15.4",
-        "html-entities": "1.2.1",
-        "http-proxy-middleware": "0.17.4",
-        "internal-ip": "1.2.0",
-        "opn": "4.0.2",
-        "portfinder": "1.0.13",
-        "selfsigned": "1.10.1",
-        "serve-index": "1.9.0",
-        "sockjs": "0.3.18",
-        "sockjs-client": "1.1.2",
-        "spdy": "3.4.7",
-        "strip-ansi": "3.0.1",
-        "supports-color": "3.2.3",
-        "webpack-dev-middleware": "1.12.0",
-        "yargs": "6.6.0"
+        "md5": "2.2.1",
+        "uglify-js": "2.8.29"
       },
       "dependencies": {
         "camelcase": {
-          "version": "3.0.0",
-          "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-3.0.0.tgz",
-          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+          "version": "1.2.1",
+          "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-1.2.1.tgz",
+          "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
           "dev": true
         },
-        "is-fullwidth-code-point": {
-          "version": "1.0.0",
-          "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz",
-          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+        "cliui": {
+          "version": "2.1.0",
+          "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-2.1.0.tgz",
+          "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
           "dev": true,
           "requires": {
-            "number-is-nan": "1.0.1"
+            "center-align": "0.1.3",
+            "right-align": "0.1.3",
+            "wordwrap": "0.0.2"
           }
         },
-        "opn": {
-          "version": "4.0.2",
-          "resolved": "http://registry.npm.taobao.org/opn/download/opn-4.0.2.tgz",
-          "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=",
+        "uglify-js": {
+          "version": "2.8.29",
+          "resolved": "http://registry.npm.taobao.org/uglify-js/download/uglify-js-2.8.29.tgz",
+          "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
           "dev": true,
           "requires": {
-            "object-assign": "4.1.1",
-            "pinkie-promise": "2.0.1"
+            "source-map": "0.5.6",
+            "uglify-to-browserify": "1.0.2",
+            "yargs": "3.10.0"
           }
         },
-        "string-width": {
-          "version": "1.0.2",
-          "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz",
-          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-          "dev": true,
-          "requires": {
-            "code-point-at": "1.1.0",
-            "is-fullwidth-code-point": "1.0.0",
-            "strip-ansi": "3.0.1"
-          }
+        "wordwrap": {
+          "version": "0.0.2",
+          "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.2.tgz",
+          "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+          "dev": true
         },
         "yargs": {
-          "version": "6.6.0",
-          "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-6.6.0.tgz",
-          "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
+          "version": "3.10.0",
+          "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-3.10.0.tgz",
+          "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
           "dev": true,
           "requires": {
-            "camelcase": "3.0.0",
-            "cliui": "3.2.0",
+            "camelcase": "1.2.1",
+            "cliui": "2.1.0",
             "decamelize": "1.2.0",
-            "get-caller-file": "1.0.2",
-            "os-locale": "1.4.0",
-            "read-pkg-up": "1.0.1",
-            "require-directory": "2.1.1",
-            "require-main-filename": "1.0.1",
-            "set-blocking": "2.0.0",
-            "string-width": "1.0.2",
-            "which-module": "1.0.0",
-            "y18n": "3.2.1",
-            "yargs-parser": "4.2.1"
-          }
-        },
-        "yargs-parser": {
-          "version": "4.2.1",
-          "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-4.2.1.tgz",
-          "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
-          "dev": true,
-          "requires": {
-            "camelcase": "3.0.0"
+            "window-size": "0.1.0"
           }
         }
       }
     },
+    "webpack-dev-middleware": {
+      "version": "1.12.0",
+      "resolved": "http://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-1.12.0.tgz",
+      "integrity": "sha1-007++y7dp+HTtdvgcolRMhllFwk=",
+      "dev": true,
+      "requires": {
+        "memory-fs": "0.4.1",
+        "mime": "1.3.6",
+        "path-is-absolute": "1.0.1",
+        "range-parser": "1.2.0",
+        "time-stamp": "2.0.0"
+      }
+    },
     "webpack-merge": {
       "version": "4.1.0",
       "resolved": "http://registry.npm.taobao.org/webpack-merge/download/webpack-merge-4.1.0.tgz",
       "version": "1.0.0",
       "resolved": "http://registry.npm.taobao.org/which-module/download/which-module-1.0.0.tgz",
       "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
-      "dev": true
+      "dev": true,
+      "optional": true
     },
     "wide-align": {
       "version": "1.1.2",
index 3cd612e..b160f9e 100644 (file)
@@ -1,11 +1,21 @@
 {
-  "name": "workflow-designer",
+  "name": "workflow-modeler",
   "version": "1.0.0",
   "license": "MIT",
+  "licenses": [
+    {
+      "type": "Apache-2.0",
+      "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+    },
+    {
+      "type": "Eclipse Public License-1.0",
+      "url": "http://www.eclipse.org/legal/epl-v10.html"
+    }
+  ],
   "scripts": {
     "ng": "ng",
-    "start": "ng serve",
-    "build": "ng build",
+    "start": "ng serve --host localhost --disable-host-check true",
+    "build": "ng build --prod --sm=true",
     "test": "ng test",
     "lint": "ng lint",
     "e2e": "ng e2e"
     "@angular/platform-browser": "^4.2.4",
     "@angular/platform-browser-dynamic": "^4.2.4",
     "@angular/router": "^4.2.4",
-    "@ngx-translate/core": "^7.2.0",
+    "@ngx-translate/core": "^8.0.0",
     "@ngx-translate/http-loader": "^1.0.2",
-    "angular-in-memory-web-api": "^0.3.2",
     "bootstrap": "4.0.0-alpha.6",
     "core-js": "^2.4.1",
     "date-fns": "^1.29.0",
     "font-awesome": "^4.7.0",
     "jquery": "^3.2.1",
     "jquery-ui": "^1.12.1",
-    "jsplumb": "2.5.0",
+    "jsplumb": "2.5.1",
     "ngx-bootstrap": "^1.9.1",
-    "ngx-tree-select": "^0.11.1",
-    "primeng": "^4.2.0-rc.1",
+    "ngx-tree-select": "^0.13.3",
+    "primeng": "^4.2.0",
     "rxjs": "^5.4.2",
     "zone.js": "^0.8.14"
   },
   "devDependencies": {
-    "@angular/cli": "1.3.1",
+    "@angular/cli": "1.4.3",
     "@angular/compiler-cli": "^4.2.4",
     "@angular/language-service": "^4.2.4",
     "@types/jasmine": "~2.5.53",
@@ -58,7 +67,7 @@
     "protractor": "~5.1.2",
     "ts-node": "~3.2.0",
     "tslint": "~5.3.2",
-    "typescript": "~2.3.3",
+    "typescript": "~2.4.2",
     "webpack": "3.5.6"
   }
 }
index 93788ec..d629bbd 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 -->
-<div class="main-content-wrapper">
-    <b4t-toolbar class="tool-bar"></b4t-toolbar>
-    <div class="design-area">
-        <menus class="design-menus"></menus>
-        <b4t-container class="design-container"></b4t-container>
-    </div>
-    <global-notice></global-notice>
+<div *ngIf="!isAuthorized" class="unauthorized-div">
+    <span>{{ 'WORKFLOW.UNAUTHORIZED' | translate }}</span>
 </div>
+<div *ngIf="isAuthorized" class="authorized-div">
+    <div *ngIf="toscaLoaded && restLoaded && typeLoaded" class="main-content-wrapper">
+        <wfm-toolbar class="tool-bar"></wfm-toolbar>
+        <div class="design-area">
+            <menus class="design-menus"></menus>
+            <wfm-container class="design-container"></wfm-container>
+        </div>
+        <wfm-notice></wfm-notice>
+    </div>
 
-<div *ngIf="isLoading" class="loading-div">
-    <div></div>
+    <div *ngIf="!(toscaLoaded && restLoaded && typeLoaded)" class="loading-div">
+        <div></div>
+    </div>
 </div>
\ No newline at end of file
index 54972b7..1579697 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 import { BroadcastService } from './services/broadcast.service';
+import { LOCATION_INITIALIZED } from '@angular/common';
+import { AuthService } from './services/auth.service';
+import { RestService } from './services/rest.service';
+import { ToscaService } from './services/tosca.service';
 
 /**
  * main component
@@ -22,9 +26,15 @@ import { BroadcastService } from './services/broadcast.service';
     templateUrl: './app.component.html',
     styleUrls: ['./app.component.css']
 })
-export class AppComponent {
+export class AppComponent implements OnInit {
+    public isAuthorized = false;
+    public toscaLoaded = false;
+    public restLoaded = false;
+    public typeLoaded = true;
 
-    constructor(translate: TranslateService, private broadcastService: BroadcastService) {
+    constructor(translate: TranslateService, private authService: AuthService,
+        private broadcastService: BroadcastService, toscaService: ToscaService,
+        restService: RestService) {
         // Init the I18n function.
         // this language will be used as a fallback when a translation isn't found in the current language
         translate.setDefaultLang('en');
@@ -43,4 +53,20 @@ export class AppComponent {
         }
         translate.use(browserLang);
     }
+
+    public ngOnInit() {
+        // this.broadcastService.openRight$.subscribe(hasRight => {
+        //     this.isAuthorized = hasRight;
+        // });
+        this.isAuthorized = true;
+        this.broadcastService.updateModelToscaConfig$.subscribe(tosca => {
+            this.toscaLoaded = true;
+        });
+        this.broadcastService.updateModelRestConfig$.subscribe(swagger => {
+            this.restLoaded = true;
+        });
+        this.broadcastService.updateNodeTypeConfig$.subscribe(type => {
+            this.typeLoaded = true;
+        });
+    }
 }
index 88ccbc1..66ea97c 100644 (file)
@@ -9,10 +9,11 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  */
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
 import { NgModule } from '@angular/core';
 import { BrowserModule } from '@angular/platform-browser';
 import { RouterModule } from '@angular/router';
+import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
 import { AccordionModule } from 'ngx-bootstrap/accordion';
 import { AlertModule, ModalModule } from 'ngx-bootstrap/index';
 import { NgxTreeSelectModule } from 'ngx-tree-select';
@@ -23,8 +24,8 @@ import { TranslateHttpLoader } from '@ngx-translate/http-loader';
 import { AppComponent } from './app.component';
 import { ContainerComponent } from './components/container/container.component';
 import { EditablePropertyComponent } from './components/editable-property/editable-property.component';
-import { NodeParametersComponent } from './components/node-parameters/node-parameters.component';
-import { ParameterTreeComponent } from './components/node-parameters/parameter-tree/parameter-tree.component';
+import { NodeParametersComponent } from './components/property/rest-task/node-parameters/node-parameters.component';
+import { ParameterTreeComponent } from './components/property/rest-task/node-parameters/parameter-tree/parameter-tree.component';
 import { NodeComponent } from './components/node/node.component';
 import { ParameterComponent } from './components/parameter/parameter.component';
 import { IntermediateCatchEventComponent } from './components/property/intermediate-catch-event/intermediate-catch-event.component';
@@ -41,25 +42,32 @@ import { ToolbarComponent } from './components/toolbar/toolbar.component';
 
 import { ResizableDirective } from './directive/resizable/resizable.directive';
 
+import { AuthService } from './services/auth.service';
 import { BroadcastService } from './services/broadcast.service';
-import { DataService } from './services/data/data.service';
+import { InterfaceService } from './services/interface.service';
 import { JsPlumbService } from './services/jsplumb.service';
 import { ModelService } from './services/model.service';
 import { NoticeService } from './services/notice.service';
 import { RestService } from './services/rest.service';
 import { SwaggerTreeConverterService } from './services/swagger-tree-converter.service';
 import { SettingService } from './services/setting.service';
+import { ToscaService } from './services/tosca.service';
 
 import { SharedModule } from './shared/shared.module';
 import { HttpService } from './util/http.service';
 import { GlobalNoticeComponent } from './components/global-notice/global-notice.component';
 import { MenusComponent } from './components/menus/menus.component';
 import { ScriptTaskComponent } from "./components/property/script-task/script-task.component";
-import { WorkflowsComponent } from './components/menus/workflows/workflows.component';
-import { WorkflowService } from './services/workflow.service';
-import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
-import { InMemoryDataService } from './services/data/in-memory-data.service';
-import { HttpModule } from '@angular/http';
+import { ToolbarNodeComponent } from "./components/toolbar/toolbar-node/toolbar-node.component";
+import { NodeTypeService } from "./services/node-type.service";
+import { DisplayInfoService } from "./services/display-info.service";
+import { ServiceTaskComponent } from './components/property/service-task/service-task.component';
+import { RestParametersComponent } from './components/property/rest-task/rest-parameters/rest-parameters.component';
+import {WfmInputModule} from "./shared/input/wfm-text-input.module";
+import { PlxTextInputModule } from "./paletx/plx-text-input/index";
+import { PlxTooltipModule } from "./paletx/plx-tooltip/plx-tooltip.module";
+import { PlxModalModule } from "./paletx/plx-modal/modal.module";
+import { PlxDatePickerModule } from "./paletx/plx-datepicker/picker.module";
 
 // AoT requires an exported function for factories
 export function HttpLoaderFactory(http: HttpClient) {
@@ -85,14 +93,17 @@ export function HttpLoaderFactory(http: HttpClient) {
         ScriptTaskComponent,
         StartEventComponent,
         ToolbarComponent,
+        ToolbarNodeComponent,
         RestConfigDetailComponent,
         RestConfigListComponent,
         ResizableDirective,
         GlobalNoticeComponent,
         MenusComponent,
-        WorkflowsComponent,
+        ServiceTaskComponent,
+        RestParametersComponent
     ],
     providers: [
+        AuthService,
         BroadcastService,
         HttpService,
         JsPlumbService,
@@ -100,28 +111,33 @@ export function HttpLoaderFactory(http: HttpClient) {
         NoticeService,
         RestService,
         SwaggerTreeConverterService,
-       DataService,
+        InterfaceService,
         SettingService,
-        WorkflowService
+        ToscaService,
+        NodeTypeService,
+        DisplayInfoService
     ],
     imports: [
         AccordionModule.forRoot(),
         AlertModule.forRoot(),
-        BrowserAnimationsModule,
         BrowserModule,
-        HttpModule,
-        InMemoryWebApiModule.forRoot(InMemoryDataService),
+        BrowserAnimationsModule,
         ModalModule.forRoot(),
         RouterModule.forRoot([]),
         SharedModule,
+        PlxTextInputModule,
+        PlxTooltipModule,
+        PlxModalModule.forRoot(),
+        PlxDatePickerModule,
         NgxTreeSelectModule.forRoot({
             allowFilter: true,
-            filterPlaceholder: 'Type your filter here...',
+            // filterPlaceholder: 'Type your filter here...',
             maxVisibleItemCount: 5,
             idField: 'id',
             textField: 'name',
             childrenField: 'children',
-            allowParentSelection: false
+            allowParentSelection: false,
+            expandMode: 'Selection'
         }),
         HttpClientModule,
         TranslateModule.forRoot({
@@ -130,7 +146,8 @@ export function HttpLoaderFactory(http: HttpClient) {
                 useFactory: HttpLoaderFactory,
                 deps: [HttpClient]
             }
-        })
+        }),
+        WfmInputModule
     ],
     bootstrap: [
         AppComponent,
index c40fbcd..40cdf7f 100644 (file)
@@ -14,9 +14,9 @@
 
 <div #mainContainer id="canvas" class="canvas" (mousedown)="canvasMouseDown($event)">
     <div id="node-selector" #nodeSelector></div>
-    <b4t-node *ngFor="let node of modelService.getNodes()" [node]="node" [rank]="10"></b4t-node>
+    <wfm-node *ngFor="let node of modelService.getNodes()" [node]="node" [rank]="10"></wfm-node>
 </div>
 
-<b4t-properties></b4t-properties>
+<wfm-properties></wfm-properties>
 
-<b4t-sequence-flow></b4t-sequence-flow>
\ No newline at end of file
+<wfm-sequence-flow></wfm-sequence-flow>
\ No newline at end of file
index 63ea84d..5f317cb 100644 (file)
@@ -16,7 +16,7 @@ import { SequenceFlow } from '../../model/workflow/sequence-flow';
 import { WorkflowElement } from '../../model/workflow/workflow-element';
 import { WorkflowNode } from '../../model/workflow/workflow-node';
 import { BroadcastService } from '../../services/broadcast.service';
-import { DataService } from '../../services/data/data.service';
+import { InterfaceService } from '../../services/interface.service';
 import { JsPlumbService } from '../../services/jsplumb.service';
 import { ModelService } from '../../services/model.service';
 
@@ -25,7 +25,7 @@ import { ModelService } from '../../services/model.service';
  * bpmn task nodes can be dropped into this canvas, and then the workflow can be edit
  */
 @Component({
-    selector: 'b4t-container',
+    selector: 'wfm-container',
     templateUrl: 'container.component.html',
     styleUrls: ['./container.component.css']
 })
@@ -40,7 +40,7 @@ export class ContainerComponent implements AfterViewChecked, AfterViewInit, OnIn
     private needInitSequence = false;
 
     constructor(private broadcastService: BroadcastService, private jsPlumbService: JsPlumbService,
-        private dataService: DataService, public modelService: ModelService) {
+        private interfaceService: InterfaceService, public modelService: ModelService) {
     }
 
     @HostListener('window:keyup.delete', ['$event']) ondelete(event: KeyboardEvent) {
@@ -74,10 +74,7 @@ export class ContainerComponent implements AfterViewChecked, AfterViewInit, OnIn
 
     public ngOnInit() {
         this.jsPlumbService.initJsPlumbInstance(this.modelService.rootNodeId);
-        this.broadcastService.backendServiceReady$.subscribe(() => {
-            this.dataService.initData();
-        });
-        this.broadcastService.planModel$.subscribe(() => {
+        this.broadcastService.initModel$.subscribe(() => {
             this.needInitSequence = true;
         });
         this.broadcastService.showProperty$.subscribe(element=>{
index 3c804ef..eb59b3c 100644 (file)
@@ -1,5 +1,22 @@
-<input class="edit pull-left" [ngModel]="name" (ngModelChange)="change($event)" (click)="startEdit()" (blur)="stopEdit()"
-    (mouseover)="showEditComponent(true)" (mouseout)="showEditComponent(false)">
-<button *ngIf="showEdit" type="button" class="btn blue1 pull-left" (click)="stopEdit();">
-    <i class="fa fa-check"></i>
-</button>
\ No newline at end of file
+<!--
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+-->
+<div class="editable-content" (click)="preEdit()">
+    <h3 class="editable-main" *ngIf="!editable" [title]="'BLUEPRINT.BP_PANE.RENAME' | translate">
+        <div class="editable-field">{{value}}</div>
+        <span><i class="fa fa-pencil"></i></span>
+    </h3>
+    <wfm-text-input *ngIf="editable" #editInput [(ngModel)]="editValue" (blur)="afterEdit()"
+                   isFocus="true" required>
+    </wfm-text-input>
+</div>
\ No newline at end of file
index ea96575..7f6ffbe 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 
-import { Component, EventEmitter, Input, Output } from '@angular/core';
+import {Component, EventEmitter, Input, Output, ViewChild} from "@angular/core";
+import {TranslateService} from "@ngx-translate/core";
+import {isArray, isObject} from "util";
+import {ModelService} from "../../services/model.service";
+import {NoticeService} from "../../services/notice.service";
+import {NodeType} from "../../model/workflow/node-type.enum";
+import {ValueSource} from "../../model/value-source.enum";
+import {JsPlumbService} from "../../services/jsplumb.service";
+import {WorkflowNode} from "../../model/workflow/workflow-node";
 
 /**
  * node or workflow-line name
  */
 @Component({
-    selector: 'b4t-editable-property',
+    selector: 'wfm-editable-property',
     templateUrl: 'editable-property.component.html',
     styleUrls: ['./editable-property.component.css']
 })
 export class EditablePropertyComponent {
-    @Input() public name: string;
-    @Output() public nameChange = new EventEmitter<string>();
-
-    public showEdit = false;
-    public isEditing = false;
-
-    public showEditComponent(isShow: boolean): void {
-        if(isShow){
-            this.showEdit = isShow;
-        }else{
-            if(!this.isEditing){
-                this.showEdit = false;
+    @Input() public value: string;
+    @Output() public valueChange = new EventEmitter<string>();
+    @ViewChild('editInput') private editInput: any;
+
+    public editValue = '';
+    public editable = false;
+
+    public preEdit(): void {
+        if (!this.editable) {
+            this.editable = true;
+            this.editValue = this.value;
+        }
+    }
+
+    public afterEdit(): void {
+        if (this.editable) {
+            this.editable = false;
+            if (this.value === this.editValue) {
+                return;
+            }
+
+            if (this.editInput.wfInput.valid) {
+                this.value = this.editValue;
+                this.valueChange.emit(this.value);
+            } else {
+                this.editValue = this.value;
             }
         }
     }
 
-    public startEdit(): void {
-        this.isEditing = true;
+    /*private validate(): boolean {
+        const nodes = this.modelService.getNodes();
+        const existNode = nodes.find(node => node.id === this.editValue);
+        if (existNode) {
+            this.translate.get('WORKFLOW.MSG.NODE_ID_SAME', {value: existNode.id}).subscribe((res: string) => {
+                this.notice.error(res, 10000);
+            });
+            return false;
+        }
+        return true;
     }
 
-    public stopEdit(): void {
-        this.isEditing = false;
-        this.showEdit = false;
+    private changeReferencedValue(): void {
+        const newNodeConnections = [];
+        const nodes = this.modelService.getNodes();
+        nodes.forEach((node: any) => {
+            this.changeConnectionReferencedValue(node, this.value, this.editValue);
+
+            if (node.type === NodeType[NodeType.restTask]) {
+                const parameters = node.parameters || [];
+                parameters.forEach(param => {
+                    this.changeRestTaskReferencedValue(param, this.value, this.editValue);
+                });
+            }
+        });
     }
 
-    public change(newName: string) {
-        this.name = newName;
-        this.nameChange.emit(this.name);
+    private changeConnectionReferencedValue(node: WorkflowNode, oldValue: string, newValue: string): void {
+        node.connection.forEach(connection => {
+            if (connection.sourceRef === oldValue) {
+                connection.sourceRef = newValue;
+            } else if (connection.targetRef === oldValue) {
+                connection.targetRef = newValue;
+            }
+        });
     }
+
+    // 当restTask类型的节点的属性中valueSource是Plan时,value的值为引用其他节点id
+    // value格式为[restTask_2].[responseBody].[name],可能有更多层,当时第一个[]里面的值为被引用节点的id
+    private changeRestTaskReferencedValue(param: any, oldValue: string, newValue: string): void {
+        if (param.valueSource === ValueSource[ValueSource.Plan]) {
+            const value = param.value || '';
+            const index = value.indexOf('].[');
+            if (index > -1) {
+                const nodeId = value.substring(1, index);
+                if (nodeId === oldValue) {
+                    param.value = '[' + newValue + value.substring(index);
+                }
+            }
+        } else if (param.valueSource === ValueSource[ValueSource.Definition]) {
+            const value = param.value;
+            if (isArray(value)) {
+                value.forEach(subValue => {
+                    this.changeRestTaskReferencedValue(subValue, oldValue, newValue);
+                });
+            } else if (isObject(value)) {
+                this.changeRestTaskReferencedValue(value, oldValue, newValue);
+            }
+        }
+    }*/
 }
index 8ed4e25..3552068 100644 (file)
@@ -17,7 +17,7 @@ import { NoticeType } from '../../model/notice-type.enum';
 import { NoticeService } from '../../services/notice.service';
 
 @Component({
-  selector: 'global-notice',
+  selector: 'wfm-notice',
   templateUrl: './global-notice.component.html',
   styleUrls: ['./global-notice.component.css']
 })
index ee758fe..9537bfd 100644 (file)
  */
 -->
 
-<div class="btn-left">
-    <p-splitButton [label]="getCurrentPlanName()" icon="fa-arrows" (onClick)="showWorkflows()" [model]="workflows"></p-splitButton>
+<div>
+  <label class="wf-name">{{name}}</label>
+  <!-- <button type="button" class="btn white btn-right" (click)="showRestConfigModal()">
+    <i class="fa fa-cog"></i>{{ 'WORKFLOW.SETTING' | translate:param }}
+  </button> -->
+  <button type="button" class="plx-btn btn-right" (click)="checkBack(confirmSave)">
+    <i class="fa fa-arrow-left"></i>{{ 'WORKFLOW.BACK' | translate }}
+  </button>
+  <button type="button" class="plx-btn plx-btn-primary btn-right" (click)="save()" [disabled]="!(canSave && hasRight)">
+    <i class="fa fa-save"></i>{{ 'WORKFLOW.SAVE' | translate }}
+  </button>
 </div>
-<div class="btn-right">
-    <button type="button" class="btn white" (click)="save()">
-        <i class="fa fa-save"></i>Save
-    </button>
-    <button type="button" class="btn white" (click)="showMicroserviceModal()">
-        <i class="fa fa-cog"></i>Setting
-    </button>
-    <button type="button" class="btn white" (click)="download()">
-            <i class="fa fa-download"></i>Download
-        </button>
-    <!-- <button type="button" class="btn white" (click)="test()">test</button> -->
-</div>
-<b4t-rest-config></b4t-rest-config>
-<b4t-workflows></b4t-workflows>
+
+<wfm-rest-config></wfm-rest-config>
+
+<template #confirmSave let-c="close" let-d="dismiss">
+  <div class="modal-header">
+      <h4 class="modal-title">{{ 'WORKFLOW.CONFIRM' | translate }}</h4>
+      <button type="button" class="close" (click)="d('Cross click')">
+          <span class="plx-ico-close-16"></span>
+      </button>
+  </div>
+  <div class="modal-body">
+      <div class="row alert-modal">
+          <span class="tip-img warning"></span>
+          <div class="tip-info">
+              <div class="alert-title">{{ 'WORKFLOW.CONFIRM_SAVE1' | translate }}</div>
+              <div class="alert-result">{{ 'WORKFLOW.CONFIRM_SAVE2' | translate }}</div>
+          </div>
+      </div>
+  </div>
+  <div class="modal-footer">
+      <div class="form-group">
+          <div class="btnGroup modal-btn">
+              <button type="button" class="plx-btn plx-btn-guide" (click)="saveBack();">{{ 'WORKFLOW.CONFIRM_SAVE_BACK' | translate }}</button>
+              <button type="button" class="plx-btn" (click)="back();">{{ 'WORKFLOW.CONFIRM_BACK' | translate }}</button>
+          </div>
+      </div>
+  </div>
+</template>
index b58ec08..1c064f2 100644 (file)
  */
 import { Component, OnInit, ViewChild } from '@angular/core';
 
-import { WorkflowService } from '../../services/workflow.service';
-import { WorkflowsComponent } from "./workflows/workflows.component";
-import { BroadcastService } from "../../services/broadcast.service";
-import { PlanModel } from "../../model/plan-model";
+import { BroadcastService } from '../../services/broadcast.service';
+import { ModelService } from '../../services/model.service';
 import { RestConfigComponent } from './rest-config/rest-config.component';
+import { AuthService } from '../../services/auth.service';
+import { InterfaceService } from '../../services/interface.service';
+import { ActivatedRoute } from '@angular/router/';
+import { PlxModal } from "../../paletx/plx-modal/modal";
 
 @Component({
-    selector: 'menus',
-    templateUrl: './menus.component.html',
-    styleUrls: ['./menus.component.css']
+  selector: 'menus',
+  templateUrl: './menus.component.html',
+  styleUrls: ['./menus.component.css']
 })
-export class MenusComponent {
-    @ViewChild(RestConfigComponent) public microserviceComponent: RestConfigComponent;
-    @ViewChild(WorkflowsComponent) public workflowsComponent: WorkflowsComponent;
-    public currentWorkflowId : string;
-    public workflows = [];
+export class MenusComponent implements OnInit {
+  @ViewChild(RestConfigComponent) public restConfigComponent: RestConfigComponent;
 
-    constructor(private broadcastService: BroadcastService, private workflowService: WorkflowService) {
-        this.broadcastService.workflows.subscribe(wfs => {
-            this.workflows.splice(0, this.workflows.length);
-            if(wfs) {
-                wfs.forEach((value, key, map) => {
-                    this.workflows.push({label: value.planName, command: () => {
-                        this.workflowSelected(key, value.plan);
-                    }});
-                });
-            }
-        });
-    }
+  public name = '';
+  public canSave = true;
+  public hasRight = false;
 
-    public save(): void {
-        this.workflowService.save();
-    }
+  constructor(private activatedRoute: ActivatedRoute, private modelService: ModelService,
+    private broadcastService: BroadcastService, private authService: AuthService,
+    private plxModal: PlxModal) { }
 
-    public showMicroserviceModal(): void {
-        this.microserviceComponent.show();
-    }
+  ngOnInit() {
+    this.activatedRoute.queryParams.subscribe(queryParams => {
+      let operation: string = queryParams.operation;
+      // default value is 'modify', which means save button is enabled.
+      this.canSave = null == operation || 'view' != operation.toLowerCase();
+    });
+    this.broadcastService.initModel.subscribe(planModel => {
+      this.name = planModel.name;
+    });
+    this.broadcastService.saveRight$.subscribe(saveRight => {
+      this.hasRight = saveRight;
+    });
+    // checkRights
+    this.authService.checkRights();
+  }
 
-    public test() {
-    }
+  public save(): void {
+    this.modelService.save();
+  }
 
-    public showWorkflows() {
-        this.workflowsComponent.show();
-    }
+  public back(): void {
+    history.back();
+  }
 
-    public workflowSelected(planId: string, planModel: PlanModel) {
-
-        this.broadcastService.broadcast(this.broadcastService.planModel, planModel);
-        this.broadcastService.broadcast(this.broadcastService.planId, planId);
+  public checkBack(component: any): void {
+    if (this.modelService.isModify()) {
+      this.plxModal.open(component, { size: 'sm' });
+    } else {
+      this.back();
     }
+  }
 
-    public getCurrentPlanName() {
-        let planName = this.workflowService.getPlanName(this.currentWorkflowId);
-        return planName ? planName : 'Workflows'
-    }
+  public saveBack(): void {
+    this.modelService.save(this.back);
+  }
+
+  public showRestConfigModal(): void {
+    this.restConfigComponent.show();
+  }
 
-    public download() {
-        const filename = this.getCurrentPlanName() + '.json';
-        const content = JSON.stringify(this.workflowService.planModel);
-        var eleLink = document.createElement('a');
-        eleLink.download = filename;
-        eleLink.style.display = 'none';
-        var blob = new Blob([content]);
-        eleLink.href = URL.createObjectURL(blob);
-        document.body.appendChild(eleLink);
-        eleLink.click();
-        document.body.removeChild(eleLink);
-    }
 }
index ea0d3c6..9550ed3 100644 (file)
@@ -1,13 +1,26 @@
+<!--
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+-->
 <div class="form-group row">
     <label class="col-md-2 form-control-label text-md-right">Name</label>
     <div class="col-md-10">
         <input class="form-control" [(ngModel)]="restConfig.name">
     </div>
 </div>
-<div class="form-group row">
+<!-- <div class="form-group row">
     <label class="col-md-2 form-control-label text-md-right">BaseUrl</label>
     <div class="col-md-10">
-        <input class="form-control" [(ngModel)]="restConfig.url">
+        <input class="form-control" [(ngModel)]="restConfig.baseUrl">
     </div>
 </div>
 <div class="form-group row">
@@ -31,5 +44,5 @@
         <textarea class="form-control" [disabled]="restConfig.dynamic" rows="8" [ngModel]="detail"
                   (ngModelChange)="onDetailChanged($event)"></textarea>
     </div>
-</div>
+</div> -->
 
index d99a9a1..e4d43d8 100644 (file)
@@ -22,7 +22,7 @@ import { RestService } from '../../../../services/rest.service';
  * The supported nodes can be dragged to container component. which will add a new node to the workflow.
  */
 @Component({
-    selector: 'b4t-rest-config-detail',
+    selector: 'wfm-rest-config-detail',
     templateUrl: 'rest-config-detail.component.html',
 })
 export class RestConfigDetailComponent implements OnChanges {
@@ -35,7 +35,7 @@ export class RestConfigDetailComponent implements OnChanges {
 
     public ngOnChanges() {
         if (this.restConfig == null) {
-            this.restConfig = new RestConfig('', '', '', '', '');
+            this.restConfig = new RestConfig('', '', '', '');
         }
         this.parseSwagger2String();
     }
index aa98bc8..f8d745c 100644 (file)
@@ -1,3 +1,16 @@
+<!--
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+-->
 <div class="scroll" style="overflow:hidden; max-height: 300px; height: 300px;">
     <div class="card">
         <div class="card-header d-flex justify-content-between align-items-center">
         </div>
 
         <ul class="list-group">
-            <li class="list-group-item d-flex justify-content-between align-items-center"
+            <!-- <li class="list-group-item d-flex justify-content-between align-items-center"
                 *ngFor="let restConfig of restService.getRestConfigs(); index as i">
                 <div (click)="onConfigSelected(restConfig)">{{restConfig.name}}</div>
                 <div class="badge badge-danger badge-pill" (click)="deleteRestConfig(i)">
                     <i class="fa fa-minus"></i>
                 </div>
-            </li>
+            </li> -->
         </ul>
     </div>
 </div>
index 43120e8..8a84c47 100644 (file)
@@ -22,7 +22,7 @@ import { RestService } from '../../../../services/rest.service';
  * The supported nodes can be dragged to container component. which will add a new node to the workflow.
  */
 @Component({
-    selector: 'b4t-rest-config-list',
+    selector: 'wfm-rest-config-list',
     templateUrl: 'rest-config-list.component.html',
 })
 export class RestConfigListComponent {
@@ -36,11 +36,9 @@ export class RestConfigListComponent {
     }
 
     public addRestConfig() {
+        // const restConfig = this.restService.addRestConfig();
 
-        const restConfig = this.restService.newRestConfig();
-        this.restService.addRestConfig(restConfig);
-
-        this.onConfigSelected(restConfig);
+        // this.onConfigSelected(restConfig);
     }
 
     public deleteRestConfig(index: number) {
index 9bd5bfc..a858b0f 100644 (file)
@@ -1,3 +1,16 @@
+<!--
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+-->
 <div class="modal fade" bsModal #restConfigModal="bs-modal" [config]="{backdrop: 'static'}"
      tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
     <div class="modal-dialog modal-lg">
             <div class="modal-body">
                 <div class="row">
                     <div class="col-sm-4">
-                        <b4t-rest-config-list (configSelected)="configSelected($event)"></b4t-rest-config-list>
+                        <wfm-rest-config-list (configSelected)="configSelected($event)"></wfm-rest-config-list>
                     </div>
                     <div class="col-sm-8">
-                        <b4t-rest-config-detail [restConfig]="currentRestConfig"></b4t-rest-config-detail>
+                        <wfm-rest-config-detail [restConfig]="currentRestConfig"></wfm-rest-config-detail>
                     </div>
                 </div>
             </div>
index 6a9c9c2..46ac3f9 100644 (file)
@@ -21,7 +21,7 @@ import { RestConfigListComponent } from './rest-config-list/rest-config-list.com
  * The supported nodes can be dragged to container component. which will add a new node to the workflow.
  */
 @Component({
-    selector: 'b4t-rest-config',
+    selector: 'wfm-rest-config',
     templateUrl: 'rest-config.component.html',
 })
 export class RestConfigComponent {
diff --git a/sdc-workflow-designer-ui/src/app/components/menus/workflows/workflows.component.html b/sdc-workflow-designer-ui/src/app/components/menus/workflows/workflows.component.html
deleted file mode 100644 (file)
index 0f6c7ff..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--\r
-/**\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- */\r
--->\r
-<div class="modal fade" bsModal #workflowsModal="bs-modal" [config]="{backdrop: 'static'}"\r
-tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">\r
-    <div class="modal-dialog">\r
-    <div class="modal-content">\r
-        <div class="modal-header">\r
-            <h4 class="modal-title pull-left">Workflows</h4>\r
-            <button type="button" class="close pull-right" aria-label="Close" (click)="workflowsModal.hide()">\r
-                <span aria-hidden="true">&times;</span>\r
-            </button>\r
-        </div>\r
-        <div class="modal-body">\r
-            <ul class="list-group">\r
-                    <li class="list-group-item d-flex justify-content-between align-items-center"\r
-                        *ngFor="let key of workflows?.keys()">\r
-                        <div style="width:380px"><input class="form-control" [(ngModel)]="workflows.get(key).planName"></div>\r
-                        <div class="badge badge-danger badge-pill" (click)="deleteWorkflow(key)">\r
-                            <i class="fa fa-minus"></i>\r
-                        </div>\r
-                    </li>\r
-                </ul>\r
-        </div>\r
-        <div class="modal-footer">\r
-            <button type="button" class="btn over-grey" (click)="addWorkflow()">Add</button>\r
-            <button type="button" class="btn over-grey" (click)="workflowsModal.hide()">close</button>\r
-        </div>\r
-    </div>\r
-    </div>\r
-</div>\r
diff --git a/sdc-workflow-designer-ui/src/app/components/menus/workflows/workflows.component.ts b/sdc-workflow-designer-ui/src/app/components/menus/workflows/workflows.component.ts
deleted file mode 100644 (file)
index afacd60..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- */\r
-\r
-import { AfterViewInit, Component, ViewChild } from '@angular/core';\r
-import { ModalDirective } from 'ngx-bootstrap/modal';\r
-\r
-import { WorkflowService } from "../../../services/workflow.service";\r
-import { PlanModel } from "../../../model/plan-model";\r
-\r
-/**\r
- * workflows component\r
- * open a model to set workflow info\r
- */\r
-@Component({\r
-    selector: 'b4t-workflows',\r
-    templateUrl: 'workflows.component.html',\r
-})\r
-export class WorkflowsComponent {\r
-    @ViewChild('workflowsModal') public workflowsModal: ModalDirective;\r
-\r
-    public workflows :Map<string, any>;\r
-\r
-    constructor(private workflowService: WorkflowService) {\r
-    }\r
-\r
-    public show() {\r
-        this.workflows = this.workflowService.getWorkflows();\r
-        // this.workflowService.getWorkflows().forEach((value, key, map) => {\r
-        //     this.workflows.push({\r
-        //         "planName": value.planName,\r
-        //         "planId": key\r
-        //     });\r
-        // });;\r
-\r
-        this.workflowsModal.show();\r
-    }\r
-\r
-    public deleteWorkflow(planId: string) {\r
-        this.workflowService.deleteWorkflow(planId);\r
-    }\r
-\r
-    public addWorkflow() {\r
-        this.workflowService.addWorkflow();\r
-    }\r
-\r
-}\r
diff --git a/sdc-workflow-designer-ui/src/app/components/node-parameters/node-parameters.component.css b/sdc-workflow-designer-ui/src/app/components/node-parameters/node-parameters.component.css
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/sdc-workflow-designer-ui/src/app/components/node-parameters/parameter-tree/parameter-tree.component.html b/sdc-workflow-designer-ui/src/app/components/node-parameters/parameter-tree/parameter-tree.component.html
deleted file mode 100644 (file)
index 5c03dc0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<p-tree *ngIf="parameters.length > 0" [value]="parameters">
-    <ng-template let-node pTemplate="default">
-        <b4t-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [valueSource]="valueSource" [planItems]="planItems"
-            [canDelete]="canDelete(node)" (paramChange)="paramChange($event, node)" (delete)="deleteTreeNode(node)"></b4t-parameter>
-    </ng-template>
-
-    <ng-template let-node pTemplate="array">
-        <b4t-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [valueSource]="getObjectValueSource()" [planItems]="planItems"
-            [canInsert]="canInsert(node)" [canDelete]="canDelete(node)" (paramChange)="paramChange($event, node)"
-            (insert)="addChildNode4ObjectArray(node)" (delete)="deleteTreeNode(node)"></b4t-parameter>
-    </ng-template>
-
-    <ng-template let-node pTemplate="object">
-        <b4t-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [valueSource]="getObjectValueSource()" [planItems]="planItems"
-            [canDelete]="canDelete(node)" (paramChange)="paramChange($event, node)" (delete)="deleteTreeNode(node)"></b4t-parameter>
-    </ng-template>
-
-    <ng-template let-node pTemplate="map">
-        <b4t-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [valueSource]="getObjectValueSource()" [planItems]="planItems"
-            [canInsert]="canInsert(node)" [canDelete]="canDelete(node)" (paramChange)="paramChange($event, node)"
-            (insert)="addChildNode4DynamicObject(node)" (delete)="deleteTreeNode(node)"></b4t-parameter>
-    </ng-template>
-</p-tree>
\ No newline at end of file
index 1b9c4b1..f0ade49 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 -->
-<div (click)="onClick($event)" (mousedown)="onMousedown()" (dblclick)="showProperties($event)" class="node" id="{{node.id}}"
-    (mouseover)="onMouseOver($event, $event.target.parentNode)" (mouseout)="onMouseOut($event, $event.target.parentNode)" [style.top]="node.position.top + 'px'"
-    [style.left]="node.position.left + 'px'" [style.width]="node.position.width + 'px'" #nodeItem>
+<div #nodeItem class="node" [id]="node.id" [title]="node.id"
+     (click)="onClick($event)" (mousedown)="onMousedown()" (dblclick)="showProperties($event)"
+     (mouseover)="onMouseOver($event, $event.target.parentNode)"
+     (mouseout)="onMouseOut($event, $event.target.parentNode)"
+     [style.top]="node.position.top + 'px'"
+     [style.left]="node.position.left + 'px'" [style.width]="node.position.width + 'px'">
 
-    <div class="name">{{node.name}}</div>
+    <div *ngIf="!isGatewayNodeType(node.type)" class="name">
+        {{node.name}}
+    </div>
 
-    <div *ngIf="canHaveChildren()" b4tResizable class="node-icon" [style.width]="node.position.width + 'px'" [style.height]="node.position.height + 'px'"
-        [class.active]="active">
-        <b4t-node *ngFor="let child of node.children" [node]="child" [rank]="rank + 10"></b4t-node>
+    <div *ngIf="canHaveChildren()" wfmResizable class="node-icon" [style.width]="node.position.width + 'px'"
+         [style.height]="node.position.height + 'px'"
+         [class.active]="active">
+        <wfm-node *ngFor="let child of node.children" [node]="child" [rank]="rank + 10"></wfm-node>
         <div class="anchor anchors anchor-left">
             <span class="left">
                 <i class="left-arrow1"></i>
     </div>
 
     <div *ngIf="!canHaveChildren()" class="node-icon" [class.active]="active">
-        <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" [style.width]="node.position.width + 'px'" [style.height]="node.position.height + 'px'">
+        <img *ngIf='node.icon && "" != node.icon' [src]='getImageUrl(node.icon)'/>
+        <svg *ngIf='!(node.icon && "" != node.icon)' version="1.1" xmlns="http://www.w3.org/2000/svg"
+             viewBox="0 0 30 30" [style.width]="node.position.width + 'px'"
+             [style.height]="node.position.height + 'px'">
             <g [ngSwitch]="node.type">
                 <g *ngSwitchCase="nodeType[nodeType.startEvent]">
                     <path class="st0" d="M15,2c7.2,0,13,5.8,13,13s-5.8,13-13,13S2,22.2,2,15S7.8,2,15,2 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15
-                        s15-6.7,15-15S23.3,0,15,0L15,0z" />
+                        s15-6.7,15-15S23.3,0,15,0L15,0z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.endEvent]">
                     <path class="st0" d="M15,4c6.1,0,11,4.9,11,11s-4.9,11-11,11S4,21.1,4,15S8.9,4,15,4 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15
-                        s15-6.7,15-15S23.3,0,15,0L15,0z" />
+                        s15-6.7,15-15S23.3,0,15,0L15,0z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.errorStartEvent]">
                     <path class="st0" d="M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15s15-6.7,15-15S23.3,0,15,0z M15,28C7.8,28,2,22.2,2,15S7.8,2,15,2
-                        s13,5.8,13,13S22.2,28,15,28z" />
+                        s13,5.8,13,13S22.2,28,15,28z"/>
                     <path class="st0" d="M19.7,12H17l2-5.5c0.1-0.3,0.1-0.5-0.1-0.7c-0.2-0.2-0.3-0.3-0.6-0.3H14c-0.3,0-0.6,0.2-0.8,0.5L9.7,16
                         c-0.1,0.3-0.1,0.5,0.1,0.7c0.2,0.2,0.3,0.3,0.6,0.3l3.6,0.1l-1,6.7c-0.1,0.3,0.2,0.8,0.5,0.9c0.1,0,0.2,0,0.3,0
                         c0.3,0,0.7-0.2,0.9-0.4l5.5-11.1c0.1-0.3,0.1-0.5,0-0.8C20.2,12.1,19.9,12,19.7,12z M14.6,22.3l1.2-5.9c0-0.3,0-0.4-0.2-0.6
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.errorEndEvent]">
                     <path class="st0" d="M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15s15-6.7,15-15S23.3,0,15,0z M15,26C8.9,26,4,21.1,4,15S8.9,4,15,4
-                        s11,4.9,11,11S21.1,26,15,26z" />
+                        s11,4.9,11,11S21.1,26,15,26z"/>
                     <path class="st0" d="M19.7,12.4H17l2-5.5c0.1-0.3,0.1-0.5-0.1-0.7c-0.2-0.2-0.3-0.3-0.6-0.3h-4.2c-0.3,0-0.6,0.2-0.8,0.5l-3.5,10
                         c-0.1,0.3-0.1,0.5,0.1,0.7c0.2,0.2,0.3,0.3,0.6,0.3l3.6,0.1l-1,6.7c-0.1,0.3,0.2,0.8,0.5,0.9c0.1,0,0.2,0,0.3,0
-                        c0.3,0,0.7-0.2,0.9-0.4l5.5-11.1c0.1-0.3,0.1-0.5,0-0.8C20.2,12.6,20,12.4,19.7,12.4z" />
+                        c0.3,0,0.7-0.2,0.9-0.4l5.5-11.1c0.1-0.3,0.1-0.5,0-0.8C20.2,12.6,20,12.4,19.7,12.4z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.toscaNodeManagementTask]">
                     <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3
-                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />
-                    <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />
-                    <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />
-                    <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />
+                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z"/>
+                    <path class="st0"
+                          d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z"/>
+                    <path class="st0"
+                          d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z"/>
+                    <path class="st0"
+                          d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z"/>
                     <path class="st0" d="M24.7,15.1h-5c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1h1.5v5.7c0,0.6,0.4,1,1,1s1-0.4,1-1v-5.7h1.5c0.6,0,1-0.4,1-1
-                        C25.7,15.5,25.2,15.1,24.7,15.1z" />
+                        C25.7,15.5,25.2,15.1,24.7,15.1z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.restTask]">
                     <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3
-                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />
-                    <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />
-                    <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />
-                    <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />
+                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z"/>
+                    <path class="st0"
+                          d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z"/>
+                    <path class="st0"
+                          d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z"/>
+                    <path class="st0"
+                          d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z"/>
                     <path class="st0" d="M24.1,22.6l-1.6-2.7c0.9-0.4,1.5-1.2,1.5-2.2c0-1.4-1.2-2.5-2.8-2.5h-1.9c-0.2,0-0.4,0.1-0.6,0.2
                         c-0.2,0.1-0.3,0.3-0.3,0.6v7c0,0.4,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8v-2.8h0.8l1.9,3.2c0.1,0.2,0.4,0.4,0.7,0.4
                         c0.1,0,0.3,0,0.4-0.1C24.2,23.5,24.4,23,24.1,22.6z M20.1,16.8h1.2c0.6,0,1.2,0.4,1.2,0.9s-0.5,0.9-1.2,0.9h-1.2V16.8z"
                     <path class="st0" d="M29.1,12.9l-12-12c-1.1-1.1-3.1-1.1-4.2,0l-12,12C0.3,13.4,0,14.2,0,15s0.3,1.6,0.9,2.1l12,12
                         c0.6,0.6,1.3,0.9,2.1,0.9s1.6-0.3,2.1-0.9l12-12c0.6-0.6,0.9-1.3,0.9-2.1S29.7,13.4,29.1,12.9z M27.7,15.7l-12,12
                         c-0.4,0.4-1,0.4-1.4,0l-12-12C2.1,15.5,2,15.3,2,15s0.1-0.5,0.3-0.7l12-12C14.5,2.1,14.7,2,15,2s0.5,0.1,0.7,0.3l12,12
-                        c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />
+                        c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.parallelGateway]">
                     <path class="st0" d="M20.5,14H16V9.5c0-0.6-0.4-1-1-1s-1,0.4-1,1V14H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H14v4.5c0,0.6,0.4,1,1,1
-                        s1-0.4,1-1V16h4.5c0.6,0,1-0.4,1-1S21.1,14,20.5,14z" />
+                        s1-0.4,1-1V16h4.5c0.6,0,1-0.4,1-1S21.1,14,20.5,14z"/>
                     <path class="st0" d="M29.1,12.9l-12-12c-1.1-1.1-3.1-1.1-4.2,0l-12,12C0.3,13.4,0,14.2,0,15s0.3,1.6,0.9,2.1l12,12
                         c0.6,0.6,1.3,0.9,2.1,0.9s1.6-0.3,2.1-0.9l12-12c0.6-0.6,0.9-1.3,0.9-2.1S29.7,13.4,29.1,12.9z M27.7,15.7l-12,12
                         c-0.4,0.4-1,0.4-1.4,0l-12-12C2.1,15.5,2,15.3,2,15s0.1-0.5,0.3-0.7l12-12C14.5,2.1,14.7,2,15,2s0.5,0.1,0.7,0.3l12,12
-                        c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />
+                        c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.subProcess]">
                     <path class="st0" d="M24.5,1h-18c-2.8,0-5,2.2-5,5v18c0,2.8,2.2,5,5,5h18c2.8,0,5-2.2,5-5V6C29.5,3.2,27.2,1,24.5,1z M20.2,27h-9.4
                         v-9.1c0-0.3,0.2-0.5,0.5-0.5h8.4c0.3,0,0.5,0.2,0.5,0.5V27z M27.5,24c0,1.7-1.3,3-3,3h-2.3v-9.1c0-1.4-1.1-2.5-2.5-2.5h-8.4
-                        c-1.4,0-2.5,1.1-2.5,2.5V27H6.5c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h18c1.7,0,3,1.3,3,3V24z" />
+                        c-1.4,0-2.5,1.1-2.5,2.5V27H6.5c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h18c1.7,0,3,1.3,3,3V24z"/>
                     <path class="st0" d="M19,21.3h-2.5v-2.5c0-0.6-0.4-1-1-1c-0.6,0-1,0.4-1,1v2.5H12c-0.6,0-1,0.4-1,1s0.4,1,1,1h2.5v2.5
-                        c0,0.6,0.4,1,1,1c0.6,0,1-0.4,1-1v-2.5H19c0.6,0,1-0.4,1-1S19.5,21.3,19,21.3z" />
+                        c0,0.6,0.4,1,1,1c0.6,0,1-0.4,1-1v-2.5H19c0.6,0,1-0.4,1-1S19.5,21.3,19,21.3z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.intermediateCatchEvent]">
                     <path class="st0" d="M15,0C6.7,0,0,6.7,0,15c0,8.3,6.7,15,15,15c8.3,0,15-6.7,15-15C30,6.7,23.3,0,15,0z M16,27.9V26
                         c0,0.6,0.4,1,1,1s1-0.4,1-1V2.1C22.4,2.5,27.5,7.6,27.9,14H26c-0.6,0-1,0.4-1,1s0.4,1,1,1h1.9C27.5,22.4,22.4,27.5,16,27.9z"
                     />
                     <path class="st0" d="M20,14h-3.6l2.5-6.6c0.2-0.5-0.1-1.1-0.6-1.3c-0.5-0.2-1.1,0.1-1.3,0.6l-3,8c-0.1,0.3-0.1,0.7,0.1,0.9
-                        c0.2,0.3,0.5,0.4,0.8,0.4h5c0.6,0,1-0.4,1-1S20.6,14,20,14z" />
+                        c0.2,0.3,0.5,0.4,0.8,0.4h5c0.6,0,1-0.4,1-1S20.6,14,20,14z"/>
                 </g>
                 <g *ngSwitchCase="nodeType[nodeType.scriptTask]">
                     <path class="st0" d="M24,1H6C3.2,1,1,3.2,1,6v18c0,2.8,2.2,5,5,5h18c2.8,0,5-2.2,5-5V6C29,3.2,26.8,1,24,1z M16.9,3.4
                         c-0.4-0.4-0.5-0.8-0.5-1.3c0-0.5,0.2-0.9,0.5-1.3c0.4-0.4,0.8-0.5,1.3-0.5c0.5,0,0.9,0.2,1.3,0.5c0.4,0.4,0.5,0.8,0.5,1.3
                         c0,0.5-0.2,0.9-0.5,1.3l0.9,0.9c0.2,0.2,0.4,0.2,0.6,0l5.2-5.2l4.4,4.4l0.8,0.8c0.4,0.4,0.5,0.8,0.5,1.3c0,0.5-0.2,0.9-0.5,1.3v0
                         l-5.8,5.8c-0.1-0.6-0.5-1.2-0.9-1.6L14.5,21.3z M27,24c0,1.7-1.3,3-3,3h-8.6l7.9-7.9c0.7-0.7,1-1.6,1-2.5c0-0.9-0.4-1.8-1-2.5
-                        l-0.8-0.8L18.1,9l1.3-1.3c0.7-0.7,1-1.6,1-2.5c0-0.8-0.3-1.6-0.8-2.2H24c1.7,0,3,1.3,3,3V24z" />
+                        l-0.8-0.8L18.1,9l1.3-1.3c0.7-0.7,1-1.6,1-2.5c0-0.8-0.3-1.6-0.8-2.2H24c1.7,0,3,1.3,3,3V24z"/>
                     <path class="st0" d="M17.2,12.4c-0.3-0.3-0.8-0.3-1.1,0L12.6,16c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2
-                        l3.6-3.6C17.5,13.1,17.5,12.7,17.2,12.4z" />
+                        l3.6-3.6C17.5,13.1,17.5,12.7,17.2,12.4z"/>
                     <path class="st0" d="M18.9,14.2c-0.3-0.3-0.8-0.3-1.1,0l-3.6,3.6c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2
-                        c0.2,0,0.4-0.1,0.5-0.2l3.6-3.6C19.2,14.9,19.2,14.4,18.9,14.2z" />
+                        c0.2,0,0.4-0.1,0.5-0.2l3.6-3.6C19.2,14.9,19.2,14.4,18.9,14.2z"/>
                     <path class="st0" d="M17.1,20.6l3.6-3.6c0.3-0.3,0.3-0.8,0-1.1s-0.8-0.3-1.1,0L16,19.5c-0.3,0.3-0.3,0.8,0,1.1
-                        c0.1,0.1,0.3,0.2,0.5,0.2S17,20.7,17.1,20.6z" />
+                        c0.1,0.1,0.3,0.2,0.5,0.2S17,20.7,17.1,20.6z"/>
                 </g>
             </g>
         </svg>
index 5fd2cae..5482758 100644 (file)
@@ -9,22 +9,20 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  */
-import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';
-
-import { Subscription } from 'rxjs/Subscription';
-import { SubProcess } from '../../model/workflow/sub-process';
-import { WorkflowNode } from '../../model/workflow/workflow-node';
-import { BroadcastService } from '../../services/broadcast.service';
-import { JsPlumbService } from '../../services/jsplumb.service';
-import { ModelService } from '../../services/model.service';
-import { NodeType } from '../../model/workflow/node-type.enum';
+import {AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild} from "@angular/core";
+import {Subscription} from "rxjs/Subscription";
+import {WorkflowNode} from "../../model/workflow/workflow-node";
+import {BroadcastService} from "../../services/broadcast.service";
+import {JsPlumbService} from "../../services/jsplumb.service";
+import {NodeType} from "../../model/workflow/node-type.enum";
+import {WorkflowUtil} from "../../util/workflow-util";
 
 /**
  * node component represent a single workflow node.
  * every node would be rendered on the container component
  */
 @Component({
-    selector: 'b4t-node',
+    selector: 'wfm-node',
     styleUrls: ['./node.component.css'],
     templateUrl: 'node.component.html',
 })
@@ -39,8 +37,7 @@ export class NodeComponent implements AfterViewInit, OnDestroy {
     private isMoving = false;
 
     constructor(private jsPlumbService: JsPlumbService,
-        private modelService: ModelService,
-        private broadcastService: BroadcastService) {
+                private broadcastService: BroadcastService) {
     }
 
     public ngAfterViewInit() {
@@ -106,8 +103,22 @@ export class NodeComponent implements AfterViewInit, OnDestroy {
         target.classList.add('hover');
     }
 
+    public isGatewayNodeType(type: string): boolean {
+        if (type === this.nodeType[this.nodeType.exclusiveGateway] || type === this.nodeType[this.nodeType.parallelGateway]) {
+            return true;
+        }
+        return false;
+    }
+
     public showProperties(event) {
+        if (this.isGatewayNodeType(this.node.type)) {
+            return;
+        }
         event.stopPropagation();
         this.broadcastService.broadcast(this.broadcastService.showProperty, this.node);
     }
+
+    public getImageUrl(name: string): string {
+        return WorkflowUtil.GetIconFullPath(name);
+    }
 }
index 50ec044..1b91b42 100644 (file)
  */
 -->
 
-<div class="form-group">
-    <div *ngIf="showLabel" class="parameter-item" style="margin:0;">
-        <label *ngIf="true === param.required" class="form-control-required">*</label>
-        <input *ngIf="canEditName" class="form-control form-control-input" type="text" [ngModel]="param.name" (ngModelChange)="keyChange($event)">
-        <label *ngIf="!canEditName" class="form-control-label">{{param.name}}</label>
+<div *ngIf="param.show" class="parameter">
+    <div *ngIf="currentShowLabel" class="parameter-section">
+        <label *ngIf="true === param.required" class="parameter-required">*</label>
+        <input *ngIf="currentCanEditName" class="parameter-label plx-input" type="text" [ngModel]="param.name" (ngModelChange)="keyChange($event)">
+        <label *ngIf="!currentCanEditName" class="parameter-label">{{param.name}}</label>
     </div>
-    <div class="parameter-item">
-        <div *ngIf="showValue" [ngSwitch]="param.valueSource" class="parameter-item">
-            <input *ngSwitchCase="sourceEnum[sourceEnum.String]" class="form-control form-control-value" type="text" [ngModel]="param.value"
-                (ngModelChange)="valueChange($event)">
-            <input *ngSwitchCase="sourceEnum[sourceEnum.Variable]" class="form-control form-control-value" type="text" [ngModel]="param.value"
-                (ngModelChange)="valueChange($event)">
-            <tree-select *ngSwitchCase="sourceEnum[sourceEnum.Plan]" name="simpleSelect" style="vertical-align:top;" [items]="planOptions" childrenField="children"
-                #simpleSelect="ngModel" class="form-control-value" [ngModel]="planValue" (ngModelChange)="valueChange($event)"></tree-select>
-            <select *ngSwitchCase="sourceEnum[sourceEnum.Topology]" class="form-control form-control-value" type="text" [ngModel]="param.value"
-                (ngModelChange)="valueChange($event)">
-                <option *ngFor="let topology of topologyOptions" value="{{topology.value}}">{{topology.name}}</option>
-            </select>
+    <div *ngIf="currentShowValue" class="parameter-section">
+        <div *ngIf="showValueValue" class="parameter-item">
+            <div [ngSwitch]="param.valueSource" class="parameter-item">
+                <input *ngSwitchCase="valueTypeEnum[valueTypeEnum.number]" class="parameter-value plx-input" type="text" [ngModel]="param.value"
+                    (ngModelChange)="valueChange($event)" [disabled]="!currentCanEditValue">
+                <select *ngSwitchCase="valueTypeEnum[valueTypeEnum.boolean]" class="parameter-value" type="text" [ngModel]="param.value"
+                    (ngModelChange)="valueChange($event)" [disabled]="!currentCanEditValue">
+                    <option>true</option>
+                    <option>false</option>
+                </select>
+                <tree-select *ngSwitchCase="valueSourceEnum[valueSourceEnum.Plan]" name="simpleSelect" [items]="planOptions" childrenField="children"
+                    #simpleSelect="ngModel" class="parameter-value" [ngModel]="planValue" (ngModelChange)="valueChange($event)"
+                    [disabled]="!currentCanEditValue"></tree-select>
+                <select *ngSwitchCase="valueSourceEnum[valueSourceEnum.Topology]" class="parameter-value" type="text" [ngModel]="param.value"
+                    (ngModelChange)="valueChange($event)" [disabled]="!currentCanEditValue">
+                    <option *ngFor="let topology of topologyOptions" value="{{topology.value}}">{{topology.name}}
+                    </option>
+                </select>
+                <!--string, Variable-->
+                <input *ngSwitchDefault class="parameter-value plx-input" type="text" [ngModel]="param.value" (ngModelChange)="valueChange($event)"
+                    [disabled]="!currentCanEditValue">
+            </div>
         </div>
-        <select *ngIf="showValueSource" class="form-control parameter-item" style="width:auto;" type="text" [ngModel]="param.valueSource"
-            (ngModelChange)="valueSourceChange($event)">
-            <option *ngFor="let sourceType of valueSource" value="{{sourceEnum[sourceType]}}">{{sourceEnum[sourceType]}}</option>
+        <select *ngIf="showValueSource" class="parameter-item" style="width:auto;" type="text" [ngModel]="param.valueSource" (ngModelChange)="valueSourceChange($event)"
+            [disabled]="!currentCanEditValue">
+            <option *ngFor="let sourceItem of sourceItems" value="{{sourceItem.value}}">
+                {{sourceItem.name}}
+            </option>
         </select>
     </div>
-    <div *ngIf="canInsert" class="parameter-item">
-        <button type="button" class="btn blue1" (click)="insertParam()">
+    <div *ngIf="currentCanInsert" class="parameter-section">
+        <button type="button" class="plx-btn plx-btn-primary" (click)="insertParam()">
             <i class="fa fa-plus"></i>
         </button>
     </div>
-    <div *ngIf="canDelete" class="parameter-item">
-        <button type="button" class="btn oes-red-bg" (click)="deleteParam()">
+    <div *ngIf="currentCanDelete" class="parameter-section">
+        <button type="button" class="plx-btn plx-btn-error" (click)="deleteParam()">
             <i class="fa fa-minus"></i>
         </button>
     </div>
index 8c61446..c208c1d 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 
-import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
-
-import { PlanTreeviewItem } from '../../model/plan-treeview-item';
-import { ValueSource } from '../../model/value-source.enum';
-import { Parameter } from '../../model/workflow/parameter';
-import { DataService } from '../../services/data/data.service';
+import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from "@angular/core";
+import {PlanTreeviewItem} from "../../model/plan-treeview-item";
+import {ValueSource} from "../../model/value-source.enum";
+import {Parameter} from "../../model/workflow/parameter";
+import {ToscaService} from "../../services/tosca.service";
+import {ValueType} from "../../model/value-type.enum";
 
 /**
  * this component contains in property component if the corresponding node has parameter properties
  * eg. task node have input and output params, start event node has input param
  */
 @Component({
-    selector: 'b4t-parameter',
+    selector: 'wfm-parameter',
     styleUrls: ['./parameter.component.css'],
     templateUrl: 'parameter.component.html',
 })
-export class ParameterComponent implements OnChanges, OnInit {
+export class ParameterComponent implements OnInit {
     @Input() public param: Parameter;
-    @Input() public valueSource: ValueSource[];
+    @Input() public valueSource: ValueSource[] = [];
+    @Input() public showLabel: boolean;
+    @Input() public showValue: boolean;
     @Input() public canEditName: boolean;
-    @Input() public showLabel = true;
+    @Input() public canEditValue: boolean;
     @Input() public canInsert: boolean;
     @Input() public canDelete: boolean;
     @Input() public planItems: PlanTreeviewItem[];
-    @Output() public paramChange = new EventEmitter<Parameter>();
-    @Output() insert: EventEmitter<Parameter> = new EventEmitter<Parameter>();
-    @Output() delete: EventEmitter<Parameter> = new EventEmitter<Parameter>();
-
-    public sourceEnum = ValueSource;
-    public valueGroupClass;
-    public valueClass;
-    public valueSourceClass;
+    @Output() paramChange = new EventEmitter<Parameter>();
+    @Output() insert = new EventEmitter<Parameter>();
+    @Output() delete = new EventEmitter<Parameter>();
+
+    // Parameter setting
+    public currentShowLabel: boolean;
+    public currentShowValue: boolean;
+    public currentCanEditName: boolean;
+    public currentCanEditValue: boolean;
+    public currentCanInsert: boolean;
+    public currentCanDelete: boolean;
+
+    public valueTypeEnum = ValueType;
+    public valueSourceEnum = ValueSource;
+    public sourceItems: { name: string, value: string }[] = [];
     public planOptions = [];
     public topologyOptions: { name: string, value: string }[] = [];
-    public showValue = true;
+    public showValueValue = true;
     public showValueSource = true;
     public planValue: any = {};
 
-    constructor(private dataService: DataService) { }
-
-    public ngOnChanges(changes: SimpleChanges): void {
-        // if (changes.canInsert && !changes.canInsert.isFirstChange()) {
-        //     this.resetValueGroupClass(changes.canInsert.currentValue, this.canDelete);
-        // }
-        // if (changes.canDelete && !changes.canDelete.isFirstChange()) {
-        //     this.resetValueGroupClass(this.canInsert, changes.canDelete.currentValue);
-        // }
+    constructor(private toscaService: ToscaService) {
     }
 
     public ngOnInit(): void {
-        // console.warn('Parameter OnInit, parameter name is:' + this.param.name);
-        if (1 === this.valueSource.length) {
-            this.showValueSource = false;
+        this.initSetting();
+        this.topologyOptions = this.toscaService.getTopologyProperties();
+        this.initSourceItems();
+        this.initPlanValue();
+        this.setValueSource(this.param.valueSource);
+        this.initPlanTreeViewItems(this.planItems);
+    }
+
+    private initSetting():void{
+        this.currentShowLabel = this.setDefaultValue(this.showLabel, true);
+        this.currentShowValue = this.setDefaultValue(this.showValue, true);
+        this.currentCanEditName = this.setDefaultValue(this.canEditName, false);
+        this.currentCanEditValue = this.setDefaultValue(this.canEditValue, true);
+        this.currentCanInsert = this.setDefaultValue(this.canInsert, false);
+        this.currentCanDelete = this.setDefaultValue(this.canDelete, false);
+    }
+
+    private setDefaultValue(param: boolean, value: boolean): boolean {
+        return undefined === param ? value : param;
+    }
+
+    private initSourceItems(): void {
+        this.sourceItems = [];
+        if (this.param.type !== ValueType[ValueType.object] && this.param.type !== ValueType[ValueType.array]) {
+            this.sourceItems = [{
+                name: this.capitalizeFirstLetter(this.param.type),
+                value: this.param.type
+            }];
         }
-        this.topologyOptions = this.dataService.getTopologyProperties();
-        // this.valueClass = {
-        //     'col-md-7': this.showValueSource,
-        //     'col-md-12': !this.showValueSource
-        // };
-        // this.resetValueGroupClass(this.canInsert, this.canDelete);
-        this.updateValueSource(this.param.valueSource);
-        // trans plan options to tree view items.
-        this.initPlanTreeviewItems(this.planItems);
+        this.valueSource.forEach(value => {
+            this.sourceItems.push({
+                name: ValueSource[value],
+                value: ValueSource[value]
+            });
+        });
+    }
+
+    private capitalizeFirstLetter(value: string): string {
+        const firstLetter = value.substring(0, 1);
+        const remainedLetter = value.substring(1);
+        return firstLetter.toUpperCase() + remainedLetter;
+    }
+
+    private initPlanValue(): void {
         if (ValueSource[ValueSource.Plan] === this.param.valueSource) {
-            this.planValue = { id: this.param.value };
+            this.planValue = {id: this.param.value};
+        }
+    }
+
+    private setValueSource(valueSource: string): void {
+        if (ValueSource[ValueSource.Definition] === valueSource) {
+            this.showValueValue = false;
+        } else {
+            this.showValueValue = true;
         }
     }
 
+    private initPlanTreeViewItems(planTreeviewItems: PlanTreeviewItem[]): void {
+        this.planOptions = this.getTreeViewChild(planTreeviewItems);
+    }
+
+    private getTreeViewChild(planTreeviewItems: PlanTreeviewItem[]): any[] {
+        let treeviewItems = [];
+        if (undefined == planTreeviewItems || 0 === planTreeviewItems.length) {
+            // todo: debug check if it need [] or undefined.
+            return treeviewItems;
+        }
+        planTreeviewItems.forEach(item => {
+            const treeviewItem = {
+                id: item.value,
+                name: item.name,
+                disabled: false,
+                // !item.canSelect,
+                children: this.getTreeViewChild(item.children)
+            };
+            treeviewItems.push(treeviewItem);
+        });
+        return treeviewItems;
+    }
+
     public keyChange(key: string) {
         this.param.name = key;
         this.paramChange.emit(this.param);
     }
 
+    private formatValue(value: any) {
+        let result;
+        switch (this.param.valueSource) {
+            case ValueSource[ValueSource.boolean]:
+                result = value === "true" ? true : false;
+                break;
+            case ValueSource[ValueSource.integer]:
+                result = parseInt(value);
+                break;
+            case ValueSource[ValueSource.number]:
+                result = parseFloat(value);
+                break;
+            default:
+                result = value;
+        }
+        return result;
+    }
+
     public valueChange(value: any) {
         if (ValueSource[ValueSource.Plan] === this.param.valueSource) {
             if ('object' === typeof (value)) {
                 this.planValue = value;
                 this.param.value = value.id;
             } else {
-                this.planValue = { id: '' };
+                this.planValue = {id: ''};
                 this.param.value = '';
             }
         } else {
-            this.param.value = value;
+            this.param.value = this.formatValue(value);
         }
         this.paramChange.emit(this.param);
     }
 
     public valueSourceChange(valueSource: string) {
-        this.updateValueSource(valueSource);
         this.param.valueSource = valueSource;
+        this.setValueSource(valueSource);
         this.valueChange('');
     }
 
@@ -111,44 +192,4 @@ export class ParameterComponent implements OnChanges, OnInit {
     public deleteParam(): void {
         this.delete.emit();
     }
-
-    private updateValueSource(valueSource: string):void{
-        if(ValueSource[ValueSource.Definition] === valueSource){
-            this.showValue = false;
-        }else{
-            this.showValue = true;
-        }
-        // this.resetValueSourceClass(this.showValue);
-    }
-
-    private resetValueGroupClass(canInsert: boolean, canDelete: boolean): void {
-        // this.valueGroupClass = {
-        //     'col-md-5': canInsert && canDelete,
-        //     'col-md-7': (canInsert && !canDelete) || (!canInsert && canDelete),
-        //     'col-md-9': !canInsert && !canDelete
-        // };
-    }
-
-    private initPlanTreeviewItems(planTreeviewItems: PlanTreeviewItem[]): void {
-        this.planOptions = this.getTreeviewChild(planTreeviewItems);
-    }
-
-    private getTreeviewChild(planTreeviewItems: PlanTreeviewItem[]): any[] {
-        let treeviewItems = [];
-        if (undefined == planTreeviewItems || 0 === planTreeviewItems.length) {
-            // todo: debug check if it need [] or undefined.
-            return treeviewItems;
-        }
-        planTreeviewItems.forEach(item => {
-            const treeviewItem = {
-                id: item.value,
-                name: item.name,
-                disabled: false,
-                // !item.canSelect,
-                children: this.getTreeviewChild(item.children)
-            };
-            treeviewItems.push(treeviewItem);
-        });
-        return treeviewItems;
-    }
 }
index 45abdd0..2384192 100644 (file)
@@ -12,4 +12,4 @@
  *******************************************************************************/
 -->
 
-<b4t-parameter [param]="node.parameter" [valueSource]="sources"></b4t-parameter>
\ No newline at end of file
+<wfm-parameter [param]="node.parameter" [valueSource]="sources"></wfm-parameter>
\ No newline at end of file
index f8a63a1..ed11ba2 100644 (file)
@@ -16,10 +16,10 @@ import { Parameter } from '../../../model/workflow/parameter';
 import { ErrorEvent } from '../../../model/workflow/error-event';
 
 @Component({
-    selector: 'b4t-error-event',
+    selector: 'wfm-error-event',
     templateUrl: 'error-event.component.html',
 })
 export class ErrorEventComponent {
     @Input() public node: ErrorEvent;
-    public sources: ValueSource[] = [ValueSource.String];
+    public sources: ValueSource[] = [ValueSource.string];
 }
index 3395a6e..1c1e766 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
 -->
-
-<div class="form-group row">
-    <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_TYPE' | translate}}</label>
-    <div class="col-md-9">
-        <p-radioButton name="timeType" label="Duration" value="timeDuration" [ngModel]="node.timerEventDefinition.type" (ngModelChange)="timerTypeChange($event)">Duration</p-radioButton>
-        <p-radioButton name="timeType" label="Date" value="timeDate" [(ngModel)]="node.timerEventDefinition.type">Date</p-radioButton>
-        <p-radioButton name="timeType" label="Cycle" value="timeCycle" [(ngModel)]="node.timerEventDefinition.type">Cycle</p-radioButton>
-    </div>
-</div>
-
-<div *ngIf="node.timerEventDefinition.type === 'timeDuration'" class="form-group row">
-    <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_DURATION' | translate}}</label>
-    <div class="col-md-9">
-        <input type="text" class="form-control" [(ngModel)]="node.timerEventDefinition.timeDuration">
-        <label>eg: P1Y3M5DT6H7M30S</label>
+<form class="form-horizontal">
+    <div class="form-group row">
+        <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_TYPE' | translate}}</label>
+        <div class="col-md-9">
+            <label class="plx-radio-container">
+                <input type="radio" class="plx-radio" [checked]="checkedType === timeType[timeType.timeDuration]"
+                       (click)="timeTypeChange(timeType[timeType.timeDuration])">
+                <div class="radio-substitute"></div>
+                <span>{{'WORKFLOW.TIMER_CYCLE' | translate}}</span>
+            </label>&nbsp;&nbsp;
+            <label class="plx-radio-container">
+                <input type="radio" class="plx-radio" [checked]="checkedType === timeType[timeType.timeDate]"
+                       (click)="timeTypeChange(timeType[timeType.timeDate])">
+                <div class="radio-substitute"></div>
+                <span>{{'WORKFLOW.TIMER_DATE' | translate}}</span>
+            </label>
+        </div>
     </div>
-</div>
 
-<div *ngIf="node.timerEventDefinition.type === 'timeDate'" class="form-group row">
-    <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_DATE' | translate}}</label>
-    <div class="col-md-9">
-        <input type="text" class="form-control" [(ngModel)]="node.timerEventDefinition.timeDate">
-        <label>eg: 2007-04-05T12:30-02:00</label>
-        <!--
-        <p-calendar [(ngModel)]="node.timerEventDefinition.timeDate" [showIcon]="true" [showTime]="true" [showSeconds]="true"></p-calendar>
-        -->
+    <div *ngIf="checkedType === timeType[timeType.timeDuration]">
+        <!--<div class="form-group row">
+            <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_YEAR' | translate}}</label>
+            <div class="col-md-9">
+                <plx-text-input type="number" name="year" min="0" width="336px"
+                                [(ngModel)]="timeCycle.year" (change)="transformTimeDurationToString()"></plx-text-input>
+            </div>
+        </div>-->
+        <div class="form-group row">
+            <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_MONTH' | translate}}</label>
+            <div class="col-md-9">
+                <plx-text-input type="number" name="month" min="0" max="12" width="336px"
+                                [(ngModel)]="timeDuration.month" (change)="transformTimeDurationToString()"></plx-text-input>
+            </div>
+        </div>
+        <div class="form-group row">
+            <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_DAY' | translate}}</label>
+            <div class="col-md-9">
+                <plx-text-input type="number" name="day" min="0" max="31" width="336px"
+                                [(ngModel)]="timeDuration.day" (change)="transformTimeDurationToString()"></plx-text-input>
+            </div>
+        </div>
+        <div class="form-group row">
+            <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_HOUR' | translate}}</label>
+            <div class="col-md-9">
+                <plx-text-input type="number" name="hour" min="0" max="23" width="336px"
+                                [(ngModel)]="timeDuration.hour" (change)="transformTimeDurationToString()"></plx-text-input>
+            </div>
+        </div>
+        <div class="form-group row">
+            <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_MINUTE' | translate}}</label>
+            <div class="col-md-9">
+                <plx-text-input type="number" name="minute" min="0" max="59" width="336px"
+                                [(ngModel)]="timeDuration.minute" (change)="transformTimeDurationToString()"></plx-text-input>
+            </div>
+        </div>
+        <div class="form-group row">
+            <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_SECOND' | translate}}</label>
+            <div class="col-md-9">
+                <plx-text-input type="number" name="second" min="0" max="59" width="336px"
+                                [(ngModel)]="timeDuration.second" (change)="transformTimeDurationToString()"></plx-text-input>
+            </div>
+        </div>
+        <!--<div class="form-group row">
+            <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_CYCLE_INDEX' | translate}}</label>
+            <div class="col-md-9">
+                <plx-text-input type="number" name="time" min="1" width="336px"
+                                [(ngModel)]="timeCycle.time" (change)="transformTimeDurationToString()"></plx-text-input>
+            </div>
+        </div>-->
     </div>
-</div>
 
-<div *ngIf="node.timerEventDefinition.type === 'timeCycle'" class="form-group row">
-    <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_CYCLE' | translate}}</label>
-    <div class="col-md-9">
-        <input type="text"  class="form-control" [(ngModel)]="node.timerEventDefinition.timeCycle">
-        <label>eg: R5/P1Y2M10DT2H30M</label>
+    <div *ngIf="checkedType === timeType[timeType.timeDate]" class="form-group row">
+        <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.TIMER_DATE' | translate}}</label>
+        <div class="col-md-9">
+            <plx-datepicker name="date" [(ngModel)]="timeDate" [locale]="locale" (onConfirm)="timeDateChange()" showTime="true"
+                            showSeconds='true' dateFormat="YYYY/MM/DD HH:mm:ss"></plx-datepicker>
+        </div>
     </div>
-</div>
+</form>
\ No newline at end of file
index e8e2c78..d5f201f 100644 (file)
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
-import { AfterViewInit, Component, Input } from '@angular/core';
-import { Subscription } from 'rxjs/Subscription';
-
-import {IntermediateCatchEvent} from '../../../model/workflow/intermediate-catch-event';
+import {Component, Input, OnChanges, SimpleChanges, OnDestroy} from "@angular/core";
+import {IntermediateCatchEvent} from "../../../model/workflow/intermediate-catch-event";
+import {TimerEventDefinitionType} from "../../../model/workflow/timer-event-definition";
+import {TranslateService} from "@ngx-translate/core";
 
 @Component({
-    selector: 'b4t-intermediate-catch-event',
+    selector: 'wfm-intermediate-catch-event',
     templateUrl: 'intermediate-catch-event.component.html',
 })
-export class IntermediateCatchEventComponent {
+export class IntermediateCatchEventComponent implements OnChanges, OnDestroy {
     @Input() public node: IntermediateCatchEvent;
 
-    public timerTypeChange(type: string) {
+    public checkedType: string;
+    public timeType = TimerEventDefinitionType;
+    public timeDate: string;
+    public timeDuration: any = {
+        year: 0,
+        month: 0,
+        day: 0,
+        hour: 0,
+        minute: 0,
+        second: 0
+    };
+
+    public locale: any;
+    private localeZh: any = {
+        firstDayOfWeek: 0,
+        dayNames: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
+        dayNamesShort: ['日', '一', '二', '三', '四', '五', '六'],
+        monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+        monthNamesShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+        dateFns: null,
+        confirm: '确定'
+    };
+
+    constructor(private translate: TranslateService) {
+        this.locale = translate.currentLang.indexOf('zh') > -1 ? this.localeZh : undefined;
+    }
+
+    public ngOnChanges(changes: SimpleChanges): void {
+        if (this.node && this.node.timerEventDefinition) {
+            this.checkedType = this.node.timerEventDefinition.type;
+        }
+        if (!this.checkedType) {
+            this.checkedType = this.timeType[this.timeType.timeDuration];
+        } else if (this.checkedType === this.timeType[this.timeType.timeCycle]) {
+            // 兼容老数据,把timeCycle转为timeDuration
+            this.checkedType = this.node.timerEventDefinition.type = this.timeType[this.timeType.timeDuration];
+        }
+
+        if (this.node.timerEventDefinition.timeDuration) {
+            this.transformStringToTimeDuration();
+        } else if (this.node.timerEventDefinition.timeCycle) {
+            // 兼容老数据,把timeCycle转为timeDuration
+            const timeCycleArray = this.node.timerEventDefinition.timeCycle.split('/');
+            this.node.timerEventDefinition.timeDuration = timeCycleArray.length > 1 ? timeCycleArray[1] : timeCycleArray[0];
+            this.node.timerEventDefinition.timeCycle = '';
+            this.transformStringToTimeDuration();
+        } else if (this.node.timerEventDefinition.timeDate) {
+            this.transformISOToDate();
+        }
+    }
+
+    public ngOnDestroy(): void {
+        if (this.checkedType === this.timeType[this.timeType.timeDuration]) {
+            this.transformTimeDurationToString();
+        } else {
+            this.timeDateChange();
+        }
+    }
+
+    private transformStringToTimeDuration(): void {
+        // R5/P1Y2M10DT2H30M
+        // P1Y3M5DT6H7M30S
+        this.timeDuration.year = this.splitTimeDuration('P', 'Y');
+        this.timeDuration.month = this.splitTimeDuration('Y', 'M');
+        this.timeDuration.day = this.splitTimeDuration('M', 'D');
+        this.timeDuration.hour = this.splitTimeDuration('D', 'H');
+        this.timeDuration.minute = this.splitTimeDuration('H', 'M');
+        this.timeDuration.second = this.splitTimeDuration('M', 'S');
+    }
+
+    private splitTimeDuration(startKey: string, endKey: string): number {
+        const timeDuration = this.node.timerEventDefinition.timeDuration;
+        let start = timeDuration.indexOf(startKey);
+        let end = timeDuration.indexOf(endKey);
+        if (startKey === 'H' || endKey === 'S') {
+            start = timeDuration.lastIndexOf(startKey);
+            end = timeDuration.lastIndexOf(endKey);
+        }
+        const result = parseInt(timeDuration.substring(start + 1, end));
+        if (isNaN(result)) {
+            return 0;
+        } else {
+            return result;
+        }
+    }
+
+    public timeTypeChange(type: string): void {
+        this.checkedType = type;
         const timer = this.node.timerEventDefinition;
         timer.type = type;
         timer.timeCycle = '';
         timer.timeDate = '';
         timer.timeDuration = '';
     }
+
+    public transformTimeDurationToString(): void {
+        // R5/P1Y2M10DT2H30M
+        this.node.timerEventDefinition.timeDuration = 'P'
+            + this.timeDuration.year + 'Y'
+            + this.timeDuration.month + 'M'
+            + this.timeDuration.day + 'D'
+            + 'T' + this.timeDuration.hour + 'H'
+            + this.timeDuration.minute + 'M'
+            + this.timeDuration.second + 'S';
+    }
+
+    private transformISOToDate(): void {
+        this.timeDate = new Date(this.node.timerEventDefinition.timeDate).toString();
+    }
+
+    private pad(value: number): string {
+        let result = value.toString();
+        if (result.length === 1) {
+            result = '0' + result;
+        }
+        return result;
+    }
+
+    private transformDateToISO(date: Date): string {
+        return date.getFullYear() + '-' + this.pad(date.getMonth() + 1) + '-' + this.pad(date.getDate()) + 'T'
+            + this.pad(date.getHours()) + ':' + this.pad(date.getMinutes()) + ':' + this.pad(date.getSeconds());
+    }
+
+    public timeDateChange(): void {
+        // 2007-04-05T12:30-02:00
+        if (this.timeDate) {
+            const date = new Date(this.timeDate);
+            this.node.timerEventDefinition.timeDate = this.transformDateToISO(date);
+            console.log(this.node.timerEventDefinition.timeDate);
+        }
+    }
 }
index 5768c0b..a7cef5a 100644 (file)
@@ -43,7 +43,7 @@
 </div>
 <hr>
 
-<b4t-parameter *ngFor="let input of node.input" [param]="input" [valueSource]= "inputSources" [planItems]="planItems"></b4t-parameter>
+<wfm-parameter *ngFor="let input of node.input" [param]="input" [valueSource]= "inputSources" [planItems]="planItems"></wfm-parameter>
 <hr *ngIf="0 < node.input.length">
-<b4t-parameter *ngFor="let output of node.output" [param]="output" [valueSource]= "outputSources" [planItems]="planItems"></b4t-parameter>  
+<wfm-parameter *ngFor="let output of node.output" [param]="output" [valueSource]= "outputSources" [planItems]="planItems"></wfm-parameter>  
 
index 5d7339d..7fa9675 100644 (file)
@@ -18,32 +18,31 @@ import { ValueSource } from '../../../model/value-source.enum';
 import { Parameter } from '../../../model/workflow/parameter';
 import { ToscaNodeTask } from '../../../model/workflow/tosca-node-task';
 import { BroadcastService } from '../../../services/broadcast.service';
-import { DataService } from '../../../services/data/data.service';
+import { ToscaService } from '../../../services/tosca.service';
 
 /**
  * node template component provides operations about tosca modules which saved in winery.
  * This component will be used in the property component while the corresponding workflow node is calling the node template's operation
  */
 @Component({
-    selector: 'b4t-node-template',
+    selector: 'wfm-node-template',
     templateUrl: 'node-template.component.html',
 })
 export class NodeTemplateComponent implements AfterViewInit {
     @Input() public node: ToscaNodeTask;
     @Input() public planItems: PlanTreeviewItem[];
 
-    public inputSources: ValueSource[] = [ValueSource.String, ValueSource.Variable, ValueSource.Topology, ValueSource.Plan];
+    public inputSources: ValueSource[] = [ValueSource.string, ValueSource.Variable, ValueSource.Topology, ValueSource.Plan];
     public outputSources: ValueSource[] = [ValueSource.Topology, ValueSource.Plan];
     public nodeInterfaces: string[] = [];
     public nodeOperations: any[] = [];
     public nodeTemplates: NodeTemplate[] = [];
 
-    constructor(private dataService: DataService) {
+    constructor(private toscaService: ToscaService) {
     }
 
     public ngAfterViewInit() {
-        this.dataService.loadNodeTemplates()
-            .subscribe(nodeTemplates => this.nodeTemplates = nodeTemplates);
+        this.nodeTemplates = this.toscaService.getNodeTemplate();
 
         this.loadInterfaces();
         this.loadOperations();
@@ -86,7 +85,7 @@ export class NodeTemplateComponent implements AfterViewInit {
 
     private loadInterfaces() {
         if (this.node.template.id) {
-            this.dataService.loadNodeTemplateInterfaces(this.node.template)
+            this.toscaService.loadNodeTemplateInterfaces(this.node.template)
                 .subscribe(interfaces => {
                     this.nodeInterfaces = interfaces;
                 });
@@ -98,7 +97,7 @@ export class NodeTemplateComponent implements AfterViewInit {
     private loadOperations() {
         if (this.node.nodeInterface) {
             this.nodeOperations = [];
-            this.dataService.loadNodeTemplateOperations(
+            this.toscaService.loadNodeTemplateOperations(
                 this.node.template,
                 this.node.nodeInterface)
                 .subscribe(operations => this.nodeOperations = operations);
@@ -109,7 +108,7 @@ export class NodeTemplateComponent implements AfterViewInit {
 
     private loadParameters() {
         if (this.node.operation) {
-            this.dataService.loadNodeTemplateOperationParameter(
+            this.toscaService.loadNodeTemplateOperationParameter(
                 this.node.template,
                 this.node.nodeInterface,
                 this.node.operation)
@@ -118,7 +117,7 @@ export class NodeTemplateComponent implements AfterViewInit {
                     this.node.output = [];
 
                     params.input.forEach(param => {
-                        const p = new Parameter(param, '', ValueSource[ValueSource.String]);
+                        const p = new Parameter(param, '', ValueSource[ValueSource.string]);
                         this.node.input.push(p);
                     });
 
index 8aa912d..a6d25e9 100644 (file)
 
 <div class="wm-properties-wrapper" *ngIf="show">
     <div class="form-group row">
-        <b4t-editable-property class="col-md-10" [(name)]="node.name"></b4t-editable-property>
-        <div class="col-md-2">
-            <button (click)="deleteNode()" type="button" class="btn white">
-                <i class="fa fa-trash" style="margin-right: 5px;"></i>
+        <wfm-editable-property class="col-md-9" [(value)]="node.name"></wfm-editable-property>
+        <div class="col-md-3">
+            <button (click)="deleteNode()" type="button" class="plx-btn plx-btn-error">
+                <i class="plx-ico-delete-16" style="margin-right: 5px;"></i>{{ 'WORKFLOW.DELETE' | translate }}
             </button>
         </div>
     </div>
 
     <hr>
     <div [ngSwitch]="node.type">
-        <b4t-start-event *ngSwitchCase="nodeType[nodeType.startEvent]" [node]="node"></b4t-start-event>
-        <b4t-error-event *ngSwitchCase="nodeType[nodeType.errorStartEvent]" [node]="node"></b4t-error-event>
-        <b4t-error-event *ngSwitchCase="nodeType[nodeType.errorEndEvent]" [node]="node"></b4t-error-event>
-        <b4t-node-template *ngSwitchCase="nodeType[nodeType.toscaNodeManagementTask]" [node]="node" [planItems]="planTreeviewItems"></b4t-node-template>
-        <b4t-rest-task *ngSwitchCase="nodeType[nodeType.restTask]" [node]="node" [planItems]="planTreeviewItems"></b4t-rest-task>
-        <b4t-intermediate-catch-event *ngSwitchCase="nodeType[nodeType.intermediateCatchEvent]" [node]="node"></b4t-intermediate-catch-event>
-        <b4t-script-task *ngSwitchCase="nodeType[nodeType.scriptTask]" [node]="node"></b4t-script-task>
+        <wfm-start-event *ngSwitchCase="nodeType[nodeType.startEvent]" [node]="node"></wfm-start-event>
+        <wfm-error-event *ngSwitchCase="nodeType[nodeType.errorStartEvent]" [node]="node"></wfm-error-event>
+        <wfm-error-event *ngSwitchCase="nodeType[nodeType.errorEndEvent]" [node]="node"></wfm-error-event>
+        <wfm-node-template *ngSwitchCase="nodeType[nodeType.toscaNodeManagementTask]" [node]="node" [planItems]="planTreeviewItems"></wfm-node-template>
+        <wfm-rest-task *ngSwitchCase="nodeType[nodeType.restTask]" [node]="node" [planItems]="planTreeviewItems"></wfm-rest-task>
+        <wfm-intermediate-catch-event *ngSwitchCase="nodeType[nodeType.intermediateCatchEvent]" [node]="node"></wfm-intermediate-catch-event>
+        <wfm-service-task *ngSwitchCase="nodeType[nodeType.serviceTask]" [node]="node"></wfm-service-task>
+        <wfm-script-task *ngSwitchCase="nodeType[nodeType.scriptTask]" [node]="node"></wfm-script-task>
     </div>
 </div>
index 56db658..1b381c5 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 
-import { Component, OnInit } from '@angular/core';
-import { TreeNode } from 'primeng/primeng';
-import { TranslateService } from '@ngx-translate/core';
-
-import { PlanTreeviewItem } from '../../model/plan-treeview-item';
-import { ValueSource } from '../../model/value-source.enum';
-import { NodeType } from '../../model/workflow/node-type.enum';
-import { Parameter } from '../../model/workflow/parameter';
-import { WorkflowNode } from '../../model/workflow/workflow-node';
-import { BroadcastService } from '../../services/broadcast.service';
-import { JsPlumbService } from '../../services/jsplumb.service';
-import { ModelService } from '../../services/model.service';
-import { NoticeService } from '../../services/notice.service';
+import {Component, OnInit} from "@angular/core";
+import {TranslateService} from "@ngx-translate/core";
+import {PlanTreeviewItem} from "../../model/plan-treeview-item";
+import {ValueSource} from "../../model/value-source.enum";
+import {NodeType} from "../../model/workflow/node-type.enum";
+import {WorkflowNode} from "../../model/workflow/workflow-node";
+import {BroadcastService} from "../../services/broadcast.service";
+import {JsPlumbService} from "../../services/jsplumb.service";
+import {ModelService} from "../../services/model.service";
+import {NoticeService} from "../../services/notice.service";
 
 /**
  * property component presents information of a workflow node.
@@ -30,7 +27,7 @@ import { NoticeService } from '../../services/notice.service';
  * it may load information dynamically. the content may be different for different node type.
  */
 @Component({
-    selector: 'b4t-properties',
+    selector: 'wfm-properties',
     styleUrls: ['./properties.component.css'],
     templateUrl: 'properties.component.html',
 })
@@ -41,13 +38,13 @@ export class PropertiesComponent implements OnInit {
     // public nodeTypes: string[] = WorkflowNodeType;
     public show = false;
     public titleEditing = false;
-    public valueSource = [ValueSource.String];
+    public valueSource = [ValueSource.string];
 
     constructor(private broadcastService: BroadcastService,
-        private modelService: ModelService,
-        private translate: TranslateService,
-        private noticeService: NoticeService,
-        private jsPlumbService: JsPlumbService) {
+                private modelService: ModelService,
+                private translate: TranslateService,
+                private noticeService: NoticeService,
+                private jsPlumbService: JsPlumbService) {
 
     }
 
@@ -59,13 +56,13 @@ export class PropertiesComponent implements OnInit {
                 // TODOS: 1) save config info in case config info no exists on a different environment.
                 //        2) display property panel even if config info not exists for it may be adjust.
                 try {
-                  this.planTreeviewItems = this.modelService.getPlanParameters(this.node.id);
-                  this.show = true;
+                    this.planTreeviewItems = this.modelService.getPlanParameters(this.node.id);
+                    this.show = true;
                 } catch (error) {
-                  this.show = false;
-                  this.translate.get('WORKFLOW.MSG.SWAGGER_NOT_EXISTS').subscribe((res: string) => {
-                    this.noticeService.error(res);
-                  });
+                    this.show = false;
+                    this.translate.get('WORKFLOW.MSG.SWAGGER_NOT_EXISTS').subscribe((res: string) => {
+                        this.noticeService.error(res);
+                    });
                 }
             } else {
                 this.show = false;
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
 -->
-<b4t-parameter *ngFor="let param of pathParams" [param]="param" [valueSource]= "inputSources" [planItems]="planItems"></b4t-parameter>
+<wfm-parameter *ngFor="let param of pathParams" [param]="param" [valueSource]= "inputSources" [planItems]="planItems"></wfm-parameter>
 <hr *ngIf="pathParams.length > 0">
-<b4t-parameter *ngFor="let param of queryParams" [param]="param" [valueSource]= "inputSources" [planItems]="planItems"></b4t-parameter>
+<wfm-parameter *ngFor="let param of queryParams" [param]="param" [valueSource]= "inputSources" [planItems]="planItems"></wfm-parameter>
+<hr *ngIf="queryParams.length > 0">
+<wfm-parameter *ngFor="let param of headerParams" [param]="param" [valueSource]= "inputSources" [planItems]="planItems"></wfm-parameter>
 
-<b4t-parameter-tree [restConfigId]="restConfigId" [parameters]="inputParams" [valueSource]="inputSources"
-    [planItems]="planItems"></b4t-parameter-tree>
-<b4t-parameter-tree [restConfigId]="restConfigId" [parameters]="outputParams" [valueSource]="outputSources"
-    [planItems]="planItems"></b4t-parameter-tree>
+<wfm-parameter-tree [restConfigId]="restConfigId" [parameters]="inputParams" [valueSource]="inputSources"
+    [planItems]="planItems"></wfm-parameter-tree>
+<wfm-parameter-tree [restConfigId]="restConfigId" [parameters]="outputParams" [valueSource]="outputSources" [showValue]="false"
+    [planItems]="planItems"></wfm-parameter-tree>
 import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
 import { TreeNode } from 'primeng/primeng';
 
-import { PlanTreeviewItem } from '../../model/plan-treeview-item';
-import { Swagger, SwaggerResponse } from '../../model/swagger';
-import { ValueSource } from '../../model/value-source.enum';
-import { RestParameter } from '../../model/workflow/rest-parameter';
-import { BroadcastService } from '../../services/broadcast.service';
-import { SwaggerTreeConverterService } from '../../services/swagger-tree-converter.service';
-import { RestService } from "../../services/rest.service";
+import { PlanTreeviewItem } from '../../../../model/plan-treeview-item';
+import { Swagger, SwaggerResponseClass } from '../../../../model/swagger';
+import { ValueSource } from '../../../../model/value-source.enum';
+import { RestParameter } from '../../../../model/workflow/rest-parameter';
+import { BroadcastService } from '../../../../services/broadcast.service';
+import { SwaggerTreeConverterService } from '../../../../services/swagger-tree-converter.service';
+import { RestService } from "../../../../services/rest.service";
+import { SwaggerIn } from '../../../../model/workflow/swagger/swagger-in.enum';
 
 /**
  * property component presents information of a workflow node.
@@ -27,21 +28,22 @@ import { RestService } from "../../services/rest.service";
  * it may load information dynamically. the content may be different for different node type.
  */
 @Component({
-    selector: 'b4t-node-parameters',
+    selector: 'wfm-node-parameters',
     styleUrls: ['./node-parameters.component.css'],
     templateUrl: 'node-parameters.component.html',
 })
 export class NodeParametersComponent implements OnChanges {
     @Input() public swaggerInput: RestParameter[];
-    @Input() public swaggerOutput: SwaggerResponse[];
+    @Input() public swaggerOutput: SwaggerResponseClass[];
     @Input() public restConfigId: string;
     @Input() public planItems: PlanTreeviewItem[];
 
-    public inputSources: ValueSource[] = [ValueSource.String, ValueSource.Variable, ValueSource.Topology, ValueSource.Plan];
-    public outputSources: ValueSource[] = [ValueSource.Topology, ValueSource.Plan];
+    public inputSources: ValueSource[] = [ValueSource.Variable, ValueSource.Topology, ValueSource.Plan];
+    public outputSources: ValueSource[] = [];
     public valueSource = ValueSource;
-    public pathParams: any[] = [];
-    public queryParams: any[] = [];
+    public headerParams: RestParameter[] = [];
+    public pathParams: RestParameter[] = [];
+    public queryParams: RestParameter[] = [];
     public inputParams: TreeNode[] = [];
     public outputParams: TreeNode[] = [];
 
@@ -65,16 +67,26 @@ export class NodeParametersComponent implements OnChanges {
         this.pathParams = [];
         this.queryParams = [];
         this.inputParams = [];
+        this.headerParams = [];
 
         parameters.forEach(param => {
-            if (param.position === 'path') {
+            if (SwaggerIn[SwaggerIn.path] === param.position) {
                 this.pathParams.push(param);
-            } else if (param.position === 'query') {
+            } else if (SwaggerIn[SwaggerIn.query] === param.position) {
                 this.queryParams.push(param);
-            } else if (param.position === 'body') {
-                const requestTreeNode = this.swaggerTreeConverterService
-                    .schema2TreeNode(this.restService.getSwaggerInfo(this.restConfigId), 'Request Param', param.schema, param.value);
-                param.value = requestTreeNode.value;
+            } else if (SwaggerIn[SwaggerIn.header] === param.position) {
+                this.headerParams.push(param);
+            } else if (SwaggerIn[SwaggerIn.body] === param.position) {
+                let valueObject = undefined;
+                if (undefined !== param.value || undefined !== param.valueSource) {
+                    valueObject = { value: param.value, valueSource: param.valueSource };
+                }
+                const requestTreeNode = this.swaggerTreeConverterService.schema2TreeNode(this.restService.getSwaggerInfo(this.restConfigId),
+                    'Request Param', param.schema, valueObject);
+                // console.log('requestTreeNode is :');
+                // console.log(requestTreeNode.value);
+                param.value = requestTreeNode.value.value;
+                param.valueSource = requestTreeNode.value.valueSource;
                 this.inputParams.push(requestTreeNode);
             } else {
                 // TODO others param types not supported
@@ -83,11 +95,14 @@ export class NodeParametersComponent implements OnChanges {
         });
     }
 
-    public resetResponseParams(responses: SwaggerResponse[]) {
+    public resetResponseParams(responses: SwaggerResponseClass[]) {
         this.outputParams = [];
         if (0 < responses.length && responses[0].schema) {
-            const treeNode = this.swaggerTreeConverterService
-                .schema2TreeNode(this.restService.getSwaggerInfo(this.restConfigId), 'Response Params', responses[0].schema, {});
+            const treeNode = this.swaggerTreeConverterService.schema2TreeNode(
+                this.restService.getSwaggerInfo(this.restConfigId),
+                'Response Params',
+                responses[0].schema,
+                { value: {}, valueSource: ValueSource[ValueSource.Definition] });
             this.outputParams.push(treeNode);
         }
     }
diff --git a/sdc-workflow-designer-ui/src/app/components/property/rest-task/node-parameters/parameter-tree/parameter-tree.component.html b/sdc-workflow-designer-ui/src/app/components/property/rest-task/node-parameters/parameter-tree/parameter-tree.component.html
new file mode 100644 (file)
index 0000000..bc14295
--- /dev/null
@@ -0,0 +1,36 @@
+<!--
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+-->
+<p-tree class="ui-fluid" *ngIf="parameters.length > 0" [value]="parameters">
+    <ng-template let-node pTemplate="default">
+        <wfm-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [showValue]="showValue" [valueSource]="valueSource"
+            [planItems]="planItems" [canDelete]="getCanDelete(node)" (paramChange)="paramChange($event, node)" (delete)="deleteTreeNode(node)"></wfm-parameter>
+    </ng-template>
+
+    <ng-template let-node pTemplate="array">
+        <wfm-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [showValue]="showValue" [valueSource]="getObjectValueSource()"
+            [planItems]="planItems" [canInsert]="getCanInsert(node)" [canDelete]="getCanDelete(node)" (paramChange)="paramChange($event, node)"
+            (insert)="addChildNode4ObjectArray(node)" (delete)="deleteTreeNode(node)"></wfm-parameter>
+    </ng-template>
+
+    <ng-template let-node pTemplate="object">
+        <wfm-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [showValue]="showValue" [valueSource]="getObjectValueSource()"
+            [planItems]="planItems" [canDelete]="getCanDelete(node)" (paramChange)="paramChange($event, node)" (delete)="deleteTreeNode(node)"></wfm-parameter>
+    </ng-template>
+
+    <ng-template let-node pTemplate="map">
+        <wfm-parameter [param]="getParameter(node)" [canEditName]="node.keyEditable" [showValue]="showValue" [valueSource]="getObjectValueSource()"
+            [planItems]="planItems" [canInsert]="getCanInsert(node)" [canDelete]="getCanDelete(node)" (paramChange)="paramChange($event, node)"
+            (insert)="addChildNode4DynamicObject(node)" (delete)="deleteTreeNode(node)"></wfm-parameter>
+    </ng-template>
+</p-tree>
\ No newline at end of file
  *     ZTE - initial API and implementation and/or initial documentation
  */
 
-import { ChangeDetectionStrategy, Component, Input, OnChanges, Output, SimpleChange, SimpleChanges } from '@angular/core';
+import { ChangeDetectionStrategy, Component, Input, OnInit, Output } from '@angular/core';
 import { TreeNode } from 'primeng/primeng';
 
-import { PlanTreeviewItem } from '../../../model/plan-treeview-item';
-import { ValueSource } from '../../../model/value-source.enum';
-import { ValueType } from '../../../model/value-type.enum';
-import { Parameter } from '../../../model/workflow/parameter';
-import { SwaggerTreeConverterService } from '../../../services/swagger-tree-converter.service';
-import { WorkflowUtil } from '../../../util/workflow-util';
-import { Swagger } from "../../../model/swagger";
-import { RestService } from "../../../services/rest.service";
+import { PlanTreeviewItem } from '../../../../../model/plan-treeview-item';
+import { ValueSource } from '../../../../../model/value-source.enum';
+import { Parameter } from '../../../../../model/workflow/parameter';
+import { SwaggerTreeConverterService } from '../../../../../services/swagger-tree-converter.service';
+import { WorkflowUtil } from '../../../../../util/workflow-util';
+import { Swagger } from "../../../../../model/swagger";
+import { RestService } from "../../../../../services/rest.service";
 
 /**
  * parameter tree presents parameter of task node's input or output parameters.
  */
 @Component({
-    selector: 'b4t-parameter-tree',
+    selector: 'wfm-parameter-tree',
     styleUrls: ['./parameter-tree.component.css'],
     templateUrl: 'parameter-tree.component.html',
     changeDetection: ChangeDetectionStrategy.OnPush
 })
-export class ParameterTreeComponent implements OnChanges {
+export class ParameterTreeComponent implements OnInit {
     @Input() public parameters: TreeNode[];
+    @Input() public showValue: boolean;
+    @Input() public canInsert: boolean;
     @Input() public restConfigId: string;
     @Input() public valueSource: ValueSource[];
     @Input() public planItems: PlanTreeviewItem[];
 
     constructor(private restService: RestService, private swaggerTreeConverterService: SwaggerTreeConverterService) { }
 
-    public ngOnChanges(changes: SimpleChanges) {
+    public ngOnInit() {
+        if (undefined === this.showValue) {
+            this.showValue = true;
+        }
     }
 
     public getParameter(node: any): Parameter {
         // console.log('Parameter init:' + node.label +'.'+ node.type+'.'+JSON.stringify(node.value.value)+'.'+node.value.valueSource);
-        
+
         return new Parameter(node.label, node.value.value, node.value.valueSource, node.definition.type, node.definition.reqquired);
     }
 
 
     public paramChange(param: Parameter, node: any) {
         // console.log('Parameter change:' + param.name + ', Node label is:' + node.label);
-        
+
         node.value.valueSource = param.valueSource;
         node.value.value = param.value;
 
@@ -63,7 +67,7 @@ export class ParameterTreeComponent implements OnChanges {
         }
         if (node.parent) {
             node.parent.value.value[node.label] = node.value;
-        }else{
+        } else {
             // this parameter is 'request param' or 'response param'
         }
 
@@ -129,15 +133,19 @@ export class ParameterTreeComponent implements OnChanges {
         }
     }
 
-    public canInsert(node: any) {
-        if (node.value.valueSource !== ValueSource[ValueSource.Definition]) {
-            return false;
+    public getCanInsert(node: any) {
+        if (undefined === this.canInsert) {
+            if (node.value.valueSource !== ValueSource[ValueSource.Definition]) {
+                return false;
+            } else {
+                return this.isArrayObject(node) || this.isDynamicObject(node);
+            }
         } else {
-            return this.isArrayObject(node) || this.isDynamicObject(node);
+            return this.canInsert
         }
     }
 
-    public canDelete(node: any) {
+    public getCanDelete(node: any) {
         const parent = node.parent;
         if (parent &&
             (this.isArrayObject(parent) || this.isDynamicObject(parent))) {
@@ -150,7 +158,7 @@ export class ParameterTreeComponent implements OnChanges {
     public getObjectValueSource(): ValueSource[] {
         const result = [];
         this.valueSource.forEach(source => {
-            if (ValueSource.String != source) {
+            if (ValueSource.string != source) {
                 result.push(source);
             }
         });
diff --git a/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.html b/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.html
new file mode 100644 (file)
index 0000000..1d3f87a
--- /dev/null
@@ -0,0 +1,67 @@
+<!--
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+-->
+<div *ngIf="0 < queryParams.length">
+  <div class="form-group row">
+    <label class="col-md-3 form-control-label">{{'WORKFLOW.REST_INPUT_QUERY' | translate}}</label>
+    <div class="col-md-9"></div>
+  </div>
+  <wfm-parameter *ngFor="let query of queryParams; let i = index;" [param]="query" (paramChange)="onParamChange(query)" [valueSource]="inputValueSource" [planItems]="planItems"></wfm-parameter>
+  <hr>
+</div>
+
+<div *ngIf="0 < headerParams.length">
+  <div class="form-group row">
+    <label class="col-md-3 form-control-label">{{'WORKFLOW.REST_INPUT_HEADER' | translate}}</label>
+    <div class="col-md-9"></div>
+  </div>
+  <wfm-parameter *ngFor="let header of headerParams; let i = index;" [param]="header" (paramChange)="onParamChange(header)" [valueSource]="inputValueSource" [planItems]="planItems"></wfm-parameter>
+  <hr>
+</div>
+
+<div *ngIf="0 < pathParams.length">
+  <div class="form-group row">
+    <label class="col-md-3 form-control-label">{{'WORKFLOW.REST_INPUT_PATH' | translate}}</label>
+    <div class="col-md-9"></div>
+  </div>
+  <wfm-parameter *ngFor="let path of pathParams; let i = index;" [param]="path" (paramChange)="onParamChange(path)" [valueSource]="inputValueSource" [planItems]="planItems"></wfm-parameter>
+  <hr>
+</div>
+
+<div *ngIf="0 < formDataParams.length">
+  <div class="form-group row">
+    <label class="col-md-3 form-control-label">{{'WORKFLOW.REST_INPUT_FORMDATA' | translate}}</label>
+    <div class="col-md-9"></div>
+  </div>
+  <wfm-parameter *ngFor="let formData of formDataParams; let i = index;" [param]="formData" (paramChange)="onParamChange(formData)" [valueSource]="inputValueSource"
+    [planItems]="planItems"></wfm-parameter>
+  <hr>
+</div>
+
+<div *ngIf="0 < bodyParams.length">
+  <div class="form-group row">
+    <label class="col-md-3 form-control-label">{{'WORKFLOW.REST_INPUT_BODY' | translate}}</label>
+    <div class="col-md-9"></div>
+  </div>
+  <wfm-parameter-tree [parameters]="bodyParams" [valueSource]="inputValueSource" [planItems]="planItems"></wfm-parameter-tree>
+  <hr>
+</div>
+
+<div *ngIf="0 < responseParams.length">
+  <div class="form-group row">
+    <label class="col-md-3 form-control-label">{{'WORKFLOW.REST_OUTPUT' | translate}}</label>
+    <div class="col-md-9"></div>
+  </div>
+  <wfm-parameter-tree [parameters]="responseParams" [valueSource]="outputValueSource" [showValue]="false" [canInsert]="false"></wfm-parameter-tree>
+  <hr>
+</div>
\ No newline at end of file
diff --git a/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.spec.ts b/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.spec.ts
new file mode 100644 (file)
index 0000000..f0154f2
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RestParametersComponent } from './rest-parameters.component';
+
+describe('RestParametersComponent', () => {
+  let component: RestParametersComponent;
+  let fixture: ComponentFixture<RestParametersComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ RestParametersComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(RestParametersComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should be created', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.ts b/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-parameters/rest-parameters.component.ts
new file mode 100644 (file)
index 0000000..d24486d
--- /dev/null
@@ -0,0 +1,367 @@
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+import { Component, Input, OnInit } from '@angular/core';
+import { PlanTreeviewItem } from '../../../../model/plan-treeview-item';
+import { SwaggerBaseParameter } from '../../../../model/workflow/swagger/swagger-base-parameter';
+import { SwaggerResponse } from '../../../../model/workflow/swagger/swagger-response';
+import { TreeNode } from 'primeng/components/common/treenode';
+import { ValueSource } from '../../../../model/value-source.enum';
+import { SwaggerIn } from '../../../../model/workflow/swagger/swagger-in.enum';
+import { SwaggerBodyParameter } from '../../../../model/workflow/swagger/swagger-body-parameter';
+import { SwaggerTreeConverterService } from '../../../../services/swagger-tree-converter.service';
+import { SwaggerSchema } from '../../../../model/workflow/swagger/swagger-schema';
+import { WorkflowUtil } from '../../../../util/workflow-util';
+import { Parameter } from '../../../../model/workflow/parameter';
+import { SwaggerNormalParameter } from '../../../../model/workflow/swagger/swagger-normal-parameter';
+import { ValueType } from '../../../../model/value-type.enum';
+import { ValueObject } from '../../../../model/value-object';
+
+@Component({
+  selector: 'wfm-rest-parameters',
+  templateUrl: './rest-parameters.component.html',
+  styleUrls: ['./rest-parameters.component.css']
+})
+export class RestParametersComponent implements OnInit {
+  @Input() public dataTypeInput: SwaggerBaseParameter[];
+  @Input() public dataTypeOutput: SwaggerResponse[];
+  @Input() public definitions: any;
+  @Input() public planItems: PlanTreeviewItem[];
+  public queryParams: Parameter[] = [];
+  public headerParams: Parameter[] = [];
+  public pathParams: Parameter[] = [];
+  public formDataParams: Parameter[] = [];
+  public bodyParams: TreeNode[] = [];
+  public responseParams: TreeNode[] = [];
+
+  public inputValueSource = [ValueSource.Variable, ValueSource.Plan, ValueSource.Topology];
+  public outputValueSource = [];
+  constructor() { }
+
+  ngOnInit() {
+    if (this.dataTypeInput) {
+      this.dataTypeInput.forEach(input => {
+        switch (input.in) {
+          case SwaggerIn[SwaggerIn.query]:
+            let query = this.normal2Parameter(input as SwaggerNormalParameter);
+            input.value = query.value;
+            input.valueSource = query.valueSource;
+            this.queryParams.push(query);
+            break;
+          case SwaggerIn[SwaggerIn.header]:
+            let header = this.normal2Parameter(input as SwaggerNormalParameter);
+            input.value = header.value;
+            input.valueSource = header.valueSource;
+            this.headerParams.push(header);
+            break;
+          case SwaggerIn[SwaggerIn.path]:
+            let path = this.normal2Parameter(input as SwaggerNormalParameter);
+            input.value = path.value;
+            input.valueSource = path.valueSource;
+            this.pathParams.push(path);
+            break;
+          case SwaggerIn[SwaggerIn.formData]:
+            let formData = this.normal2Parameter(input as SwaggerNormalParameter);
+            input.value = formData.value;
+            input.valueSource = formData.valueSource;
+            this.formDataParams.push(formData);
+            break;
+          case SwaggerIn[SwaggerIn.body]:
+            let body = this.body2TreeNode(input as SwaggerBodyParameter);
+            input.value = body.value.value;
+            input.valueSource = body.value.valueSource;
+            this.bodyParams.push(body);
+            break;
+          default:
+            console.warn(`Not support this parameters in:${input.in}`);
+            break;
+        }
+      });
+    }
+    this.responseParams.push(this.parameter2TreeNode('status',
+      { type: ValueType[ValueType.number], editable: false }, { value: '', valueSource: ValueSource.string }));
+    if (this.dataTypeOutput) {
+      this.dataTypeOutput.forEach(output => {
+        const treeNode = this.swaggerResponse2TreeNode(output as SwaggerResponse);
+        if (treeNode) {
+          this.responseParams.push(treeNode);
+        }
+      });
+    }
+  }
+
+  public onParamChange(param: Parameter) {
+    this.dataTypeInput.forEach(input => {
+      if (input.name === param.name) {
+        input.value = param.value;
+        input.valueSource = param.valueSource;
+      }
+    });
+  }
+
+  private normal2Parameter(normalParam: SwaggerNormalParameter): Parameter {
+    let finalValue;
+    let finalValueSource;
+    if (normalParam.value && normalParam.value && normalParam.valueSource) {
+      finalValue = normalParam.value;
+      finalValueSource = normalParam.valueSource;
+    } else {
+      finalValue = normalParam.default;
+      finalValueSource = ValueSource[ValueSource.string];
+    }
+    let parameter = new Parameter(normalParam.name, finalValue, finalValueSource, normalParam.type, normalParam.required, normalParam.show);
+    return parameter;
+  }
+
+  private body2TreeNode(bodyParam: SwaggerBodyParameter) {
+    return this.swaggerSchema2TreeNode(bodyParam.name, bodyParam.schema, bodyParam);
+  }
+
+  private swaggerResponse2TreeNode(responseParam: SwaggerResponse): TreeNode {
+    if (responseParam.$ref) {
+      return this.swaggerRef2TreeNode(responseParam.name, responseParam.$ref);
+    } else if (responseParam.schema) {
+      return this.swaggerSchema2TreeNode(responseParam.name, responseParam.schema);
+    } else {
+      console.log(`Unsupport response parameter:${responseParam.name}`);
+      return null;
+    }
+  }
+
+  private swaggerSchema2TreeNode(name: string | number, schema: SwaggerSchema, value?: any) {
+    if (schema.$ref) {
+      return this.swaggerRef2TreeNode(name as string, schema.$ref);
+    } else {
+      value = this.getInitValue4Param(schema, value);
+      return this.parameter2TreeNode(name, schema, value);
+    }
+  }
+
+  private swaggerRef2TreeNode(name: string, ref: string, value?: any) {
+    let definition = this.definitions[ref];
+    let refTreeNode = {
+      label: 'Unsupport Ref Parameter',
+      type: this.getTreeNodeType(ref),
+      required: definition.required,
+      children: [],
+      definition: definition,
+      value: value,
+    };
+
+    // if (value.valueSource === ValueSource[ValueSource.Definition]) {
+    //   if (definition.type === 'object') {
+    //     refTreeNode.children = this.getPropertyFromObject(definition, value.value);
+    //   } else if (definition.type === 'array') {
+    //     refTreeNode.children = this.setChildrenForArray(definition, value.value);
+    //   }
+    // }
+    return refTreeNode;
+  }
+
+  private getInitValue4Param(schema: SwaggerSchema, value: any) {
+    let definition = schema;
+    if (schema.$ref) {
+      definition = this.definitions[schema.$ref];
+    }
+    let valueObject: ValueObject = { valueSource: ValueSource[ValueSource.string] };
+    if (undefined == value) {
+      valueObject.value = definition.default;
+      if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
+        valueObject.valueSource = ValueSource[ValueSource.Definition];
+      } else {
+        valueObject.valueSource = definition.type;
+      }
+    } else {
+      if('object' != typeof(value)){
+        console.error('Param value is not object!, param definition is:' + definition);
+      }
+      valueObject.valueSource = value.valueSource;
+      valueObject.value = undefined === value.value ? definition.default : value.value;
+    }
+    if (ValueType[ValueType.object] === definition.type) {
+      return this.getInitValue4Object(valueObject);
+    } else if (ValueType[ValueType.array] === definition.type) {
+      // if (undefined == value) {
+      //   valueObject.value = definition.default;
+      //   if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
+      //     valueObject.valueSource = ValueSource[ValueSource.Definition];
+      //   } else {
+      //     valueObject.valueSource = definition.type;
+      //   }
+      // } else {
+      //   valueObject.valueSource = value.valueSource;
+      //   valueObject.value = undefined === value.value ? definition.default : value.value;
+      // }
+      return this.getInitValue4Array(valueObject);
+    } else { // primary type
+      // valueObject.value = undefined === value ? definition.default : value;
+      // valueObject.valueSource = definition.type;
+      return this.getInitValue4Primary(valueObject);
+    }
+  }
+
+
+  private getInitValue4Object(value: any) {
+    const newValue = {
+      value: {},
+      valueSource: ValueSource[ValueSource.Definition]
+    };
+
+    if (!value || '' === value) {
+      return newValue;
+    } else {
+      if (value.valueSource !== ValueSource[ValueSource.Definition]) {
+        return value;
+      } else {
+        if (typeof value.value !== 'object') {
+          value.value = {};
+        }
+        return value;
+      }
+    }
+  }
+
+  private getInitValue4Array(value: any) {
+    const newValue = {
+      value: [],
+      valueSource: ValueSource[ValueSource.Definition]
+    };
+
+    if (!value || '' === value) {
+      return newValue;
+    } else {
+      if (value.valueSource !== ValueSource[ValueSource.Definition]) {
+        return value;
+      } else {
+        if (!(value.value instanceof Array)) {
+          value.value = [];
+        }
+        return value;
+      }
+    }
+  }
+
+  private getInitValue4Primary(value: any) {
+    const newValue = {
+      value: '',
+      valueSource: ValueSource[ValueSource.string]
+    };
+
+    if (!value) {
+      return newValue;
+    } else {
+      if (typeof value.value === 'object') {
+        value.value = '';
+      }
+      return value;
+    }
+  }
+
+  private parameter2TreeNode(name: string | number, definition: any, value: any): any {
+    const nodeType = this.getTreeNodeType(definition);
+
+    const node = {
+      label: name,
+      type: nodeType,
+      required: definition.required,
+      children: [],
+      definition: definition,
+      value: value
+    };
+
+    if (value.valueSource === ValueSource[ValueSource.Definition]) {
+      if (ValueType[ValueType.object] === definition.type) {
+        node.children = this.getPropertyFromObject(definition, value.value);
+      } else if (ValueType[ValueType.array] === definition.type) {
+        node.children = this.getItemsFromArray(definition, value.value);
+      }
+    }
+
+    return node;
+  }
+
+  private getTreeNodeType(param: any): string {
+    const type = param.type;
+    if (ValueType[ValueType.array] === type) {
+      return 'array';
+    } else if (ValueType[ValueType.object] === type) {
+      if (param.additionalProperties) {
+        return 'map';
+      } else {
+        return 'object';
+      }
+    } else {
+      return 'default';
+    }
+  }
+
+  private getPropertyFromObject(schema: SwaggerSchema, value: any): TreeNode[] {
+    if (schema.properties) {
+      const required = schema.required as string[];
+      return this.getPropertyFromSimpleObject(schema.properties, value, required);
+    } else if (schema.additionalProperties) {
+      return this.getPropertyFromMapOrDictionary(schema.additionalProperties, value);
+    } else {
+      console.warn('getPropertyFromObject() return [], param is:' + JSON.stringify(schema));
+      return [];
+    }
+
+  }
+
+  private getPropertyFromSimpleObject(properties: any, objectValue: any, required: string[]): TreeNode[] {
+    const treeNodes: TreeNode[] = [];
+    for (const key in properties) {
+      let property = properties[key];
+      // init required property
+      property.required = false;
+      if (Array.isArray(required)) {
+        for (let index = 0; index < required.length; index++) {
+          if (required[index] === key) {
+            property.required = true;
+            break;
+          }
+        }
+      }
+
+      objectValue[key] = this.getInitValue4Param(property, objectValue[key]);
+
+      const treeNode = this.swaggerSchema2TreeNode(key, property, objectValue[key]);
+      treeNodes.push(treeNode);
+    }
+    return treeNodes;
+  }
+
+  private getPropertyFromMapOrDictionary(additionalProperties: any, mapOrDictionary: any): TreeNode[] {
+    const treeNodes: TreeNode[] = [];
+    for (const key in mapOrDictionary) {
+      const propertyCopy = WorkflowUtil.deepClone(additionalProperties);
+      propertyCopy.value = mapOrDictionary[key];
+      const treeNode = this.swaggerSchema2TreeNode(key, propertyCopy, propertyCopy.value);
+      treeNode.keyEditable = true;
+      treeNodes.push(treeNode);
+      if (mapOrDictionary[key] !== propertyCopy.value) {
+        mapOrDictionary[key] = propertyCopy.value;
+      }
+    }
+    return treeNodes;
+  }
+
+  private getItemsFromArray(definition: any, value: any[]): any[] {
+    const children = [];
+    value.forEach((itemValue, index) => {
+      const itemCopy = WorkflowUtil.deepClone(definition.items);
+      children.push(this.swaggerSchema2TreeNode(index, itemCopy, itemValue));
+    });
+
+    return children;
+  }
+
+}
index e0d368d..d3f4192 100644 (file)
 <div class="form-group row">
        <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.REST_SERVICE' | translate}}</label>
        <div class="col-md-9">
-               <select class="form-control" [ngModel]="node.restConfigId" (ngModelChange)="serviceChanged($event)">
+               <select *ngIf="loadSwaggerByMSB" class="form-control" [ngModel]="node.restConfigId" (ngModelChange)="serviceChanged($event)">
                        <option *ngFor="let restConfig of restService.getRestConfigs()" value="{{restConfig.id}}">{{restConfig.id}}</option>
                </select>
+               <input *ngIf="!loadSwaggerByMSB" class="form-control" [ngModel]="node.restConfigId" disabled />
        </div>
 </div>
 
 <div class="form-group row">
        <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.REST_PATH' | translate}}</label>
        <div class="col-md-9">
-               <select class="form-control" [ngModel]="node.path" (ngModelChange)="pathChanged($event)">
+               <select *ngIf="loadSwaggerByMSB" class="form-control" [ngModel]="node.path" (ngModelChange)="pathChanged($event)">
                        <option *ngFor="let interface of restInterfaces" value="{{interface}}">{{interface}}</option>
                </select>
+               <input *ngIf="!loadSwaggerByMSB" class="form-control" [ngModel]="node.path" disabled />
        </div>
 </div>
 
 <div class="form-group row">
        <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.REST_METHOD' | translate}}</label>
        <div class="col-md-9">
-               <select class="form-control" [ngModel]="node.method" (ngModelChange)="methodChanged($event)">
+               <select *ngIf="loadSwaggerByMSB" class="form-control" [ngModel]="node.method" (ngModelChange)="methodChanged($event)">
                        <option *ngFor="let operation of restOperations" value="{{operation}}">{{operation}}</option>
                </select>
+               <input *ngIf="!loadSwaggerByMSB" class="form-control" [ngModel]="node.method" disabled />
        </div>
 </div>
 <hr>
 
-<div class="ui-fluid">
-       <b4t-node-parameters [restConfigId]="this.node.restConfigId" [swaggerInput]="this.node.parameters" [swaggerOutput]="this.node.responses" [planItems]="planItems"></b4t-node-parameters>
+<div *ngIf="loadSwaggerByMSB">
+       <wfm-node-parameters [restConfigId]="node.restConfigId" [swaggerInput]="node.parameters" [swaggerOutput]="node.responses"
+               [planItems]="planItems"></wfm-node-parameters>
+</div>
+
+<div *ngIf="!loadSwaggerByMSB">
+       <wfm-rest-parameters [dataTypeInput]="node.parameters" [dataTypeOutput]="dataTypeOutput" [definitions]="definitions"
+               [planItems]="planItems"></wfm-rest-parameters>
 </div>
\ No newline at end of file
index 0dccee1..3def276 100644 (file)
@@ -14,7 +14,6 @@ import { Subscription } from 'rxjs/Subscription';
 import { TranslateService } from '@ngx-translate/core';
 
 import { PlanTreeviewItem } from '../../../model/plan-treeview-item';
-import { Swagger, SwaggerMethod, SwaggerParameter, SwaggerResponse } from '../../../model/swagger';
 import { ValueSource } from '../../../model/value-source.enum';
 import { ValueType } from '../../../model/value-type.enum';
 import { RestParameter } from '../../../model/workflow/rest-parameter';
@@ -23,24 +22,49 @@ import { BroadcastService } from '../../../services/broadcast.service';
 import { NoticeService } from '../../../services/notice.service';
 import { RestService } from '../../../services/rest.service';
 import { WorkflowUtil } from '../../../util/workflow-util';
+import { NodeTypeService } from '../../../services/node-type.service';
+import { NodeDataType } from '../../../model/node-data-type/node-data-type';
+import { SwaggerBaseParameter } from "../../../model/workflow/swagger/swagger-base-parameter";
+import { SwaggerResponse } from "../../../model/workflow/swagger/swagger-response";
+import { Swagger, SwaggerMethod } from '../../../model/swagger';
+import { SwaggerBodyParameter } from '../../../model/workflow/swagger/swagger-body-parameter';
+import { SwaggerNormalParameter } from '../../../model/workflow/swagger/swagger-normal-parameter';
+import { SwaggerSchema } from '../../../model/workflow/swagger/swagger-schema';
+import { SwaggerIn } from '../../../model/workflow/swagger/swagger-in.enum';
 
 @Component({
-    selector: 'b4t-rest-task',
+    selector: 'wfm-rest-task',
     templateUrl: 'rest-task.component.html',
 })
 export class RestTaskComponent implements OnInit {
     @Input() public node: RestTask;
     @Input() public planItems: PlanTreeviewItem[];
+
     public swaggerJson: any = {};
-    public restInterfaces: any[];
-    public restOperations: any = [];
+    public restInterfaces = [];
+    public restOperations = [];
+    public loadSwaggerByMSB = true;
+    // public dataTypeInput: SwaggerBaseParameter[] = [];
+    public dataTypeOutput: SwaggerResponse[] = [];
+    public definitions: SwaggerSchema;
     private swagger: Swagger;
 
-    constructor(private broadcastService: BroadcastService, public restService: RestService,
+    constructor(private nodeTypeService: NodeTypeService, private broadcastService: BroadcastService, public restService: RestService,
         private noticeService: NoticeService, private translate: TranslateService) { }
 
     public ngOnInit() {
-        this.loadInterfaces();
+        const nodeDataType = this.nodeTypeService.getNodeDataTypeById(this.node.typeId);
+        // if (nodeDataType.content && nodeDataType.content.baseUrl && nodeDataType.content.serviceName && nodeDataType.content.version
+        //     && nodeDataType.content.path && nodeDataType.content.method && nodeDataType.content.consumes) {
+        if (nodeDataType && nodeDataType.content && nodeDataType.content.baseUrl && nodeDataType.content.serviceName
+            && nodeDataType.content.serviceVersion && nodeDataType.content.path && nodeDataType.content.method) {
+            this.loadSwaggerByMSB = false;
+        }
+        if (this.loadSwaggerByMSB) {
+            this.loadInterfaces();
+        } else {
+            this.setParametersByDataType(nodeDataType);
+        }
     }
 
     public serviceChanged(configId: string) {
@@ -64,10 +88,15 @@ export class RestTaskComponent implements OnInit {
         this.updateMethodInfo();
     }
 
-    private loadInterfaces() {
+    private loadInterfaces(): void {
         if (this.node.restConfigId) {
-            this.swagger = this.restService.getSwaggerInfo(this.node.restConfigId);
+            // this.swagger = this.restService.getSwaggerInfo(this.node.restConfigId);
+            let restConfig = this.restService.getRestConfig(this.node.restConfigId);
+            this.node.baseUrl = restConfig.url;
+            this.node.serviceName = restConfig.name;
+            this.node.serviceVersion = restConfig.version;
 
+            this.swagger = restConfig.swagger;
             if (this.swagger) {
                 this.restInterfaces = [];
                 for (const key of Object.keys(this.swagger.paths)) {
@@ -82,7 +111,7 @@ export class RestTaskComponent implements OnInit {
         }
     }
 
-    private loadOperations() {
+    private loadOperations(): void {
         if (this.node.path) {
             const swaggerPath: any = this.swagger.paths[this.node.path];
 
@@ -93,7 +122,7 @@ export class RestTaskComponent implements OnInit {
         }
     }
 
-    private updateMethodInfo() {
+    private updateMethodInfo(): void {
         if (this.node.method) {
             const path: any = this.swagger.paths[this.node.path];
             const method: SwaggerMethod = path[this.node.method];
@@ -103,8 +132,10 @@ export class RestTaskComponent implements OnInit {
 
             let tempParameters: RestParameter[] = [];
             method.parameters.forEach(param => {
-                const nodeParam = new RestParameter(param.name, '', ValueSource[ValueSource.String],
-                    ValueType[ValueType.String], param.position, param.schema, param.required);
+                let defaultType = SwaggerIn[SwaggerIn.body] === param.position ? ValueType[ValueType.object] : ValueType[ValueType.string];
+                const type = param.type ? param.type : defaultType;
+                const nodeParam = new RestParameter(param.name, undefined, ValueSource[ValueSource.string],
+                    type, param.position, param.schema, param.required);
                 tempParameters.push(WorkflowUtil.deepClone(nodeParam));
             });
             this.node.parameters = tempParameters;
@@ -114,4 +145,129 @@ export class RestTaskComponent implements OnInit {
             this.node.responses = responseParams.map(param => WorkflowUtil.deepClone(param));
         }
     }
+
+    private setParametersByDataType(nodeDataType: NodeDataType): void {
+        this.node.serviceName = nodeDataType.content.serviceName;
+        this.node.serviceVersion = nodeDataType.content.serviceVersion;
+        this.node.restConfigId = this.node.serviceName;
+        if (this.node.serviceVersion) {
+            this.node.restConfigId += ('.' + this.node.serviceVersion);
+        }
+        this.node.baseUrl = nodeDataType.content.baseUrl;
+        this.node.path = nodeDataType.content.path;
+        this.node.method = nodeDataType.content.method;
+        this.node.consumes = nodeDataType.content.consumes;
+        this.node.produces = nodeDataType.content.produces;
+        this.definitions = nodeDataType.definitions;
+        if (nodeDataType.content.inputs) {
+            for (const key in nodeDataType.content.inputs) {
+                if (nodeDataType.content.inputs.hasOwnProperty(key)) {
+                    // Set default value of dataType
+                    const element = nodeDataType.content.inputs[key];
+                    let param: SwaggerBaseParameter = this.getParameterByDataType(element, key);
+                    if (param) {
+                        // Set exist value
+                        let found = false;
+                        if (this.node.parameters) {
+                            for (let p = 0; p < this.node.parameters.length; p++) {
+                                if (param.name === this.node.parameters[p].name) {
+                                    found = true;
+                                    let value = this.node.parameters[p].value;
+                                    let valueSource = this.node.parameters[p].valueSource;
+                                    param.value = value;
+                                    param.valueSource = valueSource;
+                                    this.node.parameters[p] = param;
+                                    break;
+                                }
+                            }
+                        } else {
+                            this.node.parameters = [];
+                        }
+                        if (!found) {
+                            this.node.parameters.push(param);
+                        }
+                    }
+                }
+            }
+        }
+        if (nodeDataType.content.outputs) {
+            for (const key in nodeDataType.content.outputs) {
+                if (nodeDataType.content.outputs.hasOwnProperty(key)) {
+                    // Set default value of dataType
+                    const element = nodeDataType.content.outputs[key];
+                    this.dataTypeOutput.push(this.getResponseByDataType(element, key));
+                }
+            }
+        }
+    }
+
+    private getParameterByDataType(dataTypeParameter: SwaggerBaseParameter, name: string): SwaggerBaseParameter {
+        if (!dataTypeParameter.name) {
+            dataTypeParameter.name = name;
+        }
+        if (SwaggerIn[SwaggerIn.body] === dataTypeParameter.in) {
+            return this.initBodyParam(dataTypeParameter as SwaggerBodyParameter);
+        } else {
+            return this.initNormalParam(dataTypeParameter as SwaggerNormalParameter);
+        }
+    }
+
+    private getResponseByDataType(dataTypeResponse: SwaggerResponse, name: string): SwaggerResponse {
+        let responseParam = dataTypeResponse;
+        if (!responseParam.name) {
+            responseParam.name = name;
+        }
+        return this.initResponseParam(responseParam);
+    }
+
+    private initNormalParam(normalParam: SwaggerNormalParameter): SwaggerNormalParameter {
+        let normal = WorkflowUtil.deepClone(normalParam);
+        // Set default value of dataType
+        if (undefined === normalParam.show) {
+            normal.show = true;
+        }
+        if ('path' === normalParam.in) {
+            normal.required = true;
+        } else if (undefined === normalParam.required) {
+            normal.required = false;
+        }
+        if (undefined === normalParam.allowEmptyValue) {
+            normal.allowEmptyValue = false;
+        }
+        if (undefined === normalParam.collectionFormat) {
+            normal.collectionFormat = 'csv';
+        }
+        if (undefined === normalParam.type) {
+            normal.type == ValueType[ValueType.string];
+        }
+        // editable not support
+        return normal;
+    }
+
+    private initBodyParam(bodyParam: SwaggerBodyParameter): SwaggerBodyParameter {
+        let body = WorkflowUtil.deepClone(bodyParam);
+        // Set default value of dataType
+        if (undefined === bodyParam.show) {
+            body.show = true;
+        }
+        if (undefined === bodyParam.required) {
+            body.required = false;
+        }
+        if (undefined === bodyParam.valueSource) {
+            body.valueSource = ValueSource[ValueSource.Definition];
+        }
+        if (undefined === bodyParam.schema.type) {
+            body.schema.type == ValueType[ValueType.string];
+        }
+        // $ref not support
+        if (bodyParam.$ref) {
+            console.warn('Do not support body parameter $ref.');
+        }
+        return body;
+    }
+
+    private initResponseParam(responseParam: SwaggerResponse): SwaggerResponse {
+        let response = responseParam;
+        return response;
+    }
 }
index ee1ac4d..2618321 100644 (file)
 <div class="form-group row">
     <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.SCRIPT_FORMAT' | translate}}</label>
     <div class="col-md-9">
-        <select class="form-control" [(ngModel)]="node.scriptFormat">
-                       <option *ngFor="let script of scriptOperations" value="{{script}}">{{script}}</option>
-               </select>
+        <input *ngIf='!canChangeFormat' disabled class="form-control" [(ngModel)]="node.scriptFormat" />
+        <select *ngIf='canChangeFormat' class="form-control" [(ngModel)]="node.scriptFormat">
+            <option *ngFor="let script of scriptOperations" value="{{script}}">{{script}}</option>
+        </select>
     </div>
 </div>
 
@@ -26,5 +27,4 @@
     <div class="col-md-9">
         <textarea class="form-control" type="text" rows="20" [(ngModel)]="node.script"></textarea>
     </div>
-</div>
-
+</div>
\ No newline at end of file
index 145768f..a0f5fd9 100644 (file)
@@ -9,16 +9,43 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
-import { AfterViewInit, Component, Input } from '@angular/core';
+import { Component, Input, OnInit } from '@angular/core';
 
 import { ScriptTask } from "../../../model/workflow/script-task";
+import { NodeTypeService } from '../../../services/node-type.service';
 
 @Component({
-    selector: 'b4t-script-task',
+    selector: 'wfm-script-task',
     templateUrl: 'script-task.component.html',
 })
-export class ScriptTaskComponent {
+export class ScriptTaskComponent implements OnInit {
     @Input() public node: ScriptTask;
 
-    public scriptOperations = ['JavaScript'];
+    public canChangeFormat = true;
+    public scriptOperations = ['JavaScript', 'Groovy'];
+
+    constructor(private nodeTypeService: NodeTypeService) { }
+
+    public ngOnInit() {
+        const nodeDataType = this.nodeTypeService.getNodeDataTypeById(this.node.typeId);
+        let scriptFormat = nodeDataType.content.scriptFormat;
+        // scriptFormat is not support, reset it as null;
+        if (undefined === this.scriptOperations.find(format => format == scriptFormat)) {
+            scriptFormat = null;
+        }
+        // Defined scriptFormat value, use it as default and can not change.
+        if (scriptFormat && '' != scriptFormat) {
+            this.canChangeFormat = false;
+            if (!this.node.scriptFormat || '' == this.node.scriptFormat) {
+                this.node.scriptFormat = scriptFormat;
+                this.node.script = nodeDataType.content.script;
+            }
+        } else {
+            // Default scriptFormat value should be 'JavaScript'
+            if (!this.node.scriptFormat || '' == this.node.scriptFormat) {
+                this.node.scriptFormat = 'JavaScript';
+                this.node.script = '';
+            }
+        }
+    }
 }
diff --git a/sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.html b/sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.html
new file mode 100644 (file)
index 0000000..d72914f
--- /dev/null
@@ -0,0 +1,39 @@
+<!--
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+ -->
+<div class="form-group row">
+  <label class="col-md-3 form-control-label" style="text-align:right;">{{'WORKFLOW.SERVICE_CLASS' | translate}}</label>
+  <div class="col-md-9">
+    <input class="form-control" [(ngModel)]="node.className" [disabled]="!canEdit" />
+  </div>
+</div>
+<hr>
+
+<div class="form-group row">
+  <label class="col-md-3 form-control-label">{{'WORKFLOW.SERVICE_INPUT' | translate}}</label>
+</div>
+<wfm-parameter *ngFor="let in of node.inputs; let i = index;" [param]="in" [valueSource]="inputValueSource" [canEditName]="canEdit"
+  [canEditValue]="node.editable" [canDelete]="canEdit" (delete)="deleteInput(i)"></wfm-parameter>
+<button *ngIf="canEdit" type="button" class="plx-btn" (click)="createInput();">
+    <i class="plx-ico-new-16"></i>{{ 'WORKFLOW.CREATE' | translate }}
+</button>
+<hr>
+
+<div class="form-group row">
+  <label class="col-md-3 form-control-label">{{'WORKFLOW.SERVICE_OUTPUT' | translate}}</label>
+</div>
+<wfm-parameter *ngFor="let out of node.outputs; let i = index;" [param]="out" [valueSource]="outputValueSource" [canEditName]="canEdit"
+  [canDelete]="canEdit" [showValue]="false" (delete)="deleteOutput(i)"></wfm-parameter>
+<button *ngIf="canEdit" type="button" class="plx-btn" (click)="createOutput();" style="margin-bottom:10px;">
+    <i class="plx-ico-new-16"></i>{{ 'WORKFLOW.CREATE' | translate }}
+</button>
\ No newline at end of file
diff --git a/sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.spec.ts b/sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.spec.ts
new file mode 100644 (file)
index 0000000..498adf6
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ServiceTaskComponent } from './service-task.component';
+
+describe('ServiceTaskComponent', () => {
+  let component: ServiceTaskComponent;
+  let fixture: ComponentFixture<ServiceTaskComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ServiceTaskComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ServiceTaskComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should be created', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.ts b/sdc-workflow-designer-ui/src/app/components/property/service-task/service-task.component.ts
new file mode 100644 (file)
index 0000000..48a4074
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { Component, Input, OnInit } from '@angular/core';
+import { ServiceTask } from '../../../model/workflow/service-task';
+import { NodeTypeService } from '../../../services/node-type.service';
+import { Parameter } from '../../../model/workflow/parameter';
+import { ValueSource } from '../../../model/value-source.enum';
+
+@Component({
+  selector: 'wfm-service-task',
+  templateUrl: './service-task.component.html',
+  styleUrls: ['./service-task.component.css']
+})
+export class ServiceTaskComponent implements OnInit {
+  @Input() public node: ServiceTask;
+  public canEdit = true;
+  public inputValueSource = [ValueSource.Variable];
+  public outputValueSource = [];
+  constructor(private nodeTypeService: NodeTypeService) { }
+
+  public ngOnInit() {
+    const nodeDataType = this.nodeTypeService.getNodeDataTypeById(this.node.typeId);
+    if (nodeDataType.content && nodeDataType.content.class && '' != nodeDataType.content.class) {
+      this.canEdit = false;
+    }
+    if (!this.node.className) {
+      this.node.className = '';
+      if (nodeDataType.content.class) {
+        this.node.className = nodeDataType.content.class;
+      }
+    }
+
+    let inputs = nodeDataType.content.inputs;
+    if (!this.node.inputs) {
+      // Set default value
+      this.node.inputs = [];
+      if (inputs) {
+        for (const key in inputs) {
+          if (inputs.hasOwnProperty(key)) {
+            const element = inputs[key];
+            this.node.inputs.push(new Parameter(key, element.default, ValueSource[ValueSource.string],
+              element.type, element.required, element.show));
+          }
+        }
+      }
+    } else {
+      // Load parameter value
+      // todo: 
+    }
+
+    let outputs = nodeDataType.content.outputs;
+    if (!this.node.outputs) {
+      // Set default value
+      this.node.outputs = [];
+      if (outputs) {
+        for (const key in outputs) {
+          if (outputs.hasOwnProperty(key)) {
+            const element = outputs[key];
+            this.node.outputs.push(new Parameter(key, element.default, ValueSource[ValueSource.string],
+              element.type, element.required));
+          }
+        }
+      }
+    } else {
+      // Load parameter value
+      // todo: 
+    }
+  }
+
+  public createInput(): void {
+    this.node.inputs.push(new Parameter('', '', ValueSource[ValueSource.string]));
+  }
+
+  public deleteInput(index: number): void {
+    this.node.inputs.splice(index, 1);
+  }
+  public createOutput(): void {
+    this.node.outputs.push(new Parameter('', '', ValueSource[ValueSource.string]));
+  }
+
+  public deleteOutput(index: number): void {
+    this.node.outputs.splice(index, 1);
+  }
+
+  private getParameters() {
+
+  }
+}
index d6aaafd..f48a725 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
 -->
+<table cellpadding="10px">
+    <tr>
+        <th style="width:35%;" class="plx-table-th">{{ 'WORKFLOW.PROCESS_VARIABLE' | translate }}</th>
+        <th style="width:45%;" class="plx-table-th">{{ 'WORKFLOW.PROCESS_VARIABLE_DEFAULT' | translate }}</th>
+        <th style="width:20%;" class="plx-table-th">{{ 'WORKFLOW.PROCESS_VARIABLE_OPERATION' | translate }}</th>
+    </tr>
+    <tr *ngFor="let param of node.parameters; let i = index;" class="table-body">
+        <td>
+            <input [ngModel]="param.name" (ngModelChange)="checkKey($event, i)" class="plx-input"/>
+            <span *ngIf="param.errorMsg">{{param.errorMsg}}</span>
+        </td>
+        <td>
+            <input [(ngModel)]="param.value" class="plx-input" />
+            <span *ngIf="param.errorMsg">&nbsp;</span>
+        </td>
+        <td>
+            <i class="plx-ico-delete-16 delete-icon" (click)="delete(i)"></i>
+            <span *ngIf="param.errorMsg">&nbsp;</span>
+        </td>
+    </tr>
+</table>
 
-<div class="form-group row">
-    <div class="col-md-10"></div>
-    <div class="col-md-2">
-        <button (click)="create();" type="button" class="btn blue1 pull-right">
-            <i class="fa fa-plus"></i>
-        </button>
-    </div>
-</div>
-
-<b4t-parameter *ngFor="let param of node.parameters; let i = index;" [param]="param" [canEditName]="true"
-    [valueSource]="sources" [canDelete]="true" (delete)="delete(i)"></b4t-parameter>
\ No newline at end of file
+<button (click)="create();" type="button" class="plx-btn">
+    <i class="plx-ico-new-16"></i>{{ 'WORKFLOW.PROCESS_VARIABLE_CREATE' | translate }}
+</button>
+<!-- <wfm-parameter *ngFor="let param of node.parameters; let i = index;" [param]="param" [canEditName]="true"
+    [valueSource]="sources" [canDelete]="true" (delete)="delete(i)"></wfm-parameter> -->
\ No newline at end of file
index adef329..0f72124 100644 (file)
@@ -9,7 +9,7 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
-import { Component, Input } from '@angular/core';
+import { Component, Input, OnInit } from '@angular/core';
 import { Subscription } from 'rxjs/Subscription';
 
 import { ValueSource } from '../../../model/value-source.enum';
@@ -17,20 +17,52 @@ import { Parameter } from '../../../model/workflow/parameter';
 import { StartEvent } from '../../../model/workflow/start-event';
 import { BroadcastService } from '../../../services/broadcast.service';
 import { WorkflowUtil } from '../../../util/workflow-util';
+import { TranslateService } from '@ngx-translate/core';
 
 @Component({
-    selector: 'b4t-start-event',
+    selector: 'wfm-start-event',
+    styleUrls: ['./start-event.component.css'],
     templateUrl: 'start-event.component.html',
 })
-export class StartEventComponent {
+export class StartEventComponent implements OnInit {
     @Input() public node: StartEvent;
-    public sources: ValueSource[] = [ValueSource.String];
+    public sources: ValueSource[] = [ValueSource.string];
+
+    constructor(private translate: TranslateService) { }
+
+    ngOnInit() { }
 
     public create(): void {
-        this.node.parameters.push(new Parameter('', '', ValueSource[ValueSource.String]));
+        let parameter = new Parameter('', '', ValueSource[ValueSource.string]);
+        this.node.parameters.push(parameter);
     }
 
     public delete(index: number): void {
         this.node.parameters.splice(index, 1);
     }
+
+    public checkKey(newName: string, index: number): void {
+        this.node.parameters[index].name = newName;
+        this.node.parameters.forEach(parameter => {
+            parameter.errorMsg = '';
+        });
+        if (!newName) {
+            this.translate.get('WORKFLOW.MSG.VARIABLE_EMPTY').subscribe((res: string) => {
+                this.node.parameters[index].errorMsg = res;
+            });
+        }
+        this.node.parameters.forEach((parameter, i) => {
+            if (i + 1 < this.node.parameters.length) {
+                for (let j = i + 1; j < this.node.parameters.length; j++) {
+                    let element = this.node.parameters[j];
+                    if (element.name && parameter.name === element.name) {
+                        this.translate.get('WORKFLOW.MSG.VARIABLE_SAME').subscribe((res: string) => {
+                            parameter.errorMsg = res;
+                            element.errorMsg = res;
+                        });
+                    }
+                }
+            }
+        });
+    }
 }
index e7096ab..e9d4d22 100644 (file)
@@ -29,7 +29,7 @@
         </div>
     </div>
 
-    <div class="form-group row">
+    <!-- <div class="form-group row">
         <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.CONNECTION_SOURCE' | translate}}</label>
         <div class="col-md-9">
             <input class="form-control" disabled type="text" [(ngModel)]="sequenceFlow.sourceRef">
@@ -41,9 +41,9 @@
         <div class="col-md-9">
             <input class="form-control" disabled type="text" [(ngModel)]="sequenceFlow.targetRef">
         </div>
-    </div>
+    </div> -->
 
-    <div class="form-group row">
+    <div *ngIf="showCondition(sequenceFlow.sourceRef)" class="form-group row">
         <label class="col-md-3 form-control-label text-md-right">{{'WORKFLOW.CONNECTION_CONDITION' | translate}}</label>
         <div class="col-md-9">
             <input class="form-control" type="text" [(ngModel)]="sequenceFlow.condition">
index f132a07..55d051f 100644 (file)
@@ -17,6 +17,7 @@ import { SequenceFlow } from '../../model/workflow/sequence-flow';
 import { BroadcastService } from '../../services/broadcast.service';
 import { JsPlumbService } from '../../services/jsplumb.service';
 import { ModelService } from '../../services/model.service';
+import { NodeType } from '../../model/workflow/node-type.enum';
 
 /**
  * property component presents information of a workflow node.
@@ -24,7 +25,7 @@ import { ModelService } from '../../services/model.service';
  * it may load information dynamically. the content may be different for different node type.
  */
 @Component({
-    selector: 'b4t-sequence-flow',
+    selector: 'wfm-sequence-flow',
     styleUrls: ['./sequence-flow.component.css'],
     templateUrl: 'sequence-flow.component.html',
 })
@@ -33,8 +34,8 @@ export class SequenceFlowComponent implements AfterViewInit {
     public show = false;
 
     constructor(private broadcastService: BroadcastService,
-                private modelService: ModelService,
-                private jsPlumbService: JsPlumbService) {
+        private modelService: ModelService,
+        private jsPlumbService: JsPlumbService) {
 
     }
 
@@ -49,6 +50,19 @@ export class SequenceFlowComponent implements AfterViewInit {
         });
     }
 
+    public showCondition(sourceRef: string): boolean {
+        if (sourceRef) {
+            let node = this.modelService.getNodeMap().get(sourceRef);
+            if (node && (NodeType[NodeType.parallelGateway] === node.type || NodeType[NodeType.exclusiveGateway] === node.type)) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
     public nameChanged(name: string) {
         this.sequenceFlow.name = name;
         this.jsPlumbService.setLabel(this.sequenceFlow.sourceRef, this.sequenceFlow.targetRef, name);
diff --git a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar-node/toolbar-node.component.html b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar-node/toolbar-node.component.html
new file mode 100644 (file)
index 0000000..790273d
--- /dev/null
@@ -0,0 +1,28 @@
+<!--\r
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+ -->\r
+<accordion-group *ngFor="let category of nodeCategories" [isOpen]="category.collapse" #group>\r
+    <div accordion-heading class="toolbar-head">\r
+        <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': group?.isOpen, 'fa-chevron-right': !group?.isOpen}"></i>\r
+        <i class="fa fa-th-list"></i>\r
+        <span>{{ getDisplayName(category) }}</span>\r
+    </div>\r
+    <div *ngFor="let nodeType of category.nodes">\r
+        <div *ngIf="(nodeType.type === nodeTypeEnum[nodeTypeEnum.restTask] && supportRest) || (nodeType.type !== nodeTypeEnum[nodeTypeEnum.restTask])"\r
+             [attr.name]="getDisplayName(nodeType)" [attr.nodeTypeId]="nodeType.id" [attr.nodeType]="nodeType.type"\r
+             class="item ui-draggable">\r
+            <img [src]="getImageUrl(nodeType)"/>\r
+            <span>{{ getDisplayName(nodeType) }}</span>\r
+        </div>\r
+    </div>\r
+</accordion-group>
\ No newline at end of file
diff --git a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar-node/toolbar-node.component.ts b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar-node/toolbar-node.component.ts
new file mode 100644 (file)
index 0000000..3e82687
--- /dev/null
@@ -0,0 +1,128 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+import { Component, OnInit } from "@angular/core";\r
+import { TranslateService } from "@ngx-translate/core";\r
+import { NodeTypeService } from "../../../services/node-type.service";\r
+import { DisplayInfoService } from "../../../services/display-info.service";\r
+import { NodeDataType } from "../../../model/node-data-type/node-data-type";\r
+import { NodeType } from "../../../model/workflow/node-type.enum";\r
+import { JsPlumbService } from "../../../services/jsplumb.service";\r
+import { SettingService } from "../../../services/setting.service";\r
+import { WorkflowUtil } from "../../../util/workflow-util";\r
+\r
+@Component({\r
+    selector: 'wfm-toolbar-node',\r
+    templateUrl: 'toolbar-node.component.html',\r
+    styleUrls: ['../toolbar.component.css']\r
+})\r
+export class ToolbarNodeComponent implements OnInit {\r
+    public nodeCategories: any[] = [];\r
+    public nodeTypeEnum = NodeType;\r
+    public supportRest: boolean;\r
+\r
+    private needInitButton = false;\r
+\r
+    constructor(private nodeTypeService: NodeTypeService,\r
+        private displayInfoService: DisplayInfoService,\r
+        private jsPlumbService: JsPlumbService,\r
+        private settingService: SettingService,\r
+        public translate: TranslateService) {\r
+\r
+    }\r
+\r
+    public ngOnInit(): void {\r
+        this.settingService.getSetting().subscribe(setting => {\r
+            this.initSetting(setting);\r
+            this.displayInfoService.getDisplayInfo().subscribe(resp => {\r
+                this.initNodeCategories(resp);\r
+                this.needInitButton = true;\r
+            });\r
+        });\r
+    }\r
+\r
+    public ngAfterViewChecked(): void {\r
+        if (this.needInitButton) {\r
+            console.log('initJsPlumb');\r
+            this.initJsPlumb();\r
+            this.needInitButton = false;\r
+        }\r
+    }\r
+\r
+    private initSetting(setting: any): void {\r
+        this.supportRest = setting.supportRestNode;\r
+    }\r
+\r
+    private initJsPlumb(): void {\r
+        this.jsPlumbService.buttonDraggable();\r
+        this.jsPlumbService.buttonDroppable();\r
+    }\r
+\r
+    private initNodeCategories(displayInfo: any): void {\r
+        const defaultCategory = this.insertDefaultCategory();\r
+\r
+        const categoryData = displayInfo['categoryData'] || {};\r
+        for (let key in categoryData) {\r
+            const group = {\r
+                id: key,\r
+                displayName: categoryData[key].displayName,\r
+                collapse: categoryData[key].collapse || false,\r
+                nodes: []\r
+            };\r
+            this.nodeCategories.push(group);\r
+        }\r
+\r
+        const defaultNodes = displayInfo['nodes'] || {};\r
+        for (let nodeId in defaultNodes) {\r
+            const nodeType = this.nodeTypeService.getNodeDataTypeById(nodeId);\r
+            const node = defaultNodes[nodeId];\r
+            if (node && node.category) {\r
+                const nodeCategory = this.nodeCategories.find(category => category.id === node.category);\r
+                if (nodeCategory) {\r
+                    nodeCategory.nodes.push(nodeType);\r
+                } else {\r
+                    defaultCategory.nodes.push(nodeType);\r
+                }\r
+            } else {\r
+                defaultCategory.nodes.push(nodeType);\r
+            }\r
+        }\r
+    }\r
+\r
+    private insertDefaultCategory(): any {\r
+        this.nodeCategories = [];\r
+        const defaultCategory = {\r
+            id: 'default',\r
+            displayName: {\r
+                zh_CN: '任务',\r
+                en_US: 'Task'\r
+            },\r
+            collapse: true,\r
+            nodes: []\r
+        };\r
+        this.nodeCategories.push(defaultCategory);\r
+\r
+        return defaultCategory;\r
+    }\r
+\r
+    public getDisplayName(data: any): string {\r
+        let language = 'zh_CN';\r
+        if (this.translate.currentLang.indexOf('en') > -1) {\r
+            language = 'en_US';\r
+        }\r
+        return data.displayName ? data.displayName[language] : data.id;\r
+    }\r
+\r
+    public getImageUrl(nodeType: NodeDataType): string {\r
+        const name = nodeType && nodeType.icon ? nodeType.icon.name : '';\r
+        return WorkflowUtil.GetIconFullPath(name);\r
+    }\r
+}
\ No newline at end of file
index 19df5ef..b8e0ae7 100644 (file)
@@ -18,7 +18,7 @@
             <i class="fa fa-th-list"></i>
             <span>{{ 'WORKFLOW.BPMN_EVENT' | translate }}</span>
         </div>
-        <div nodeType="startEvent" class="item ui-draggable">
+        <div [attr.name]="'WORKFLOW.START_EVENT' | translate" nodeType="startEvent" class="item ui-draggable">
             <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
                 <g>
                     <path class="st0" d="M15,2c7.2,0,13,5.8,13,13s-5.8,13-13,13S2,22.2,2,15S7.8,2,15,2 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15
@@ -27,7 +27,7 @@
             </svg>
             <span>{{ 'WORKFLOW.START_EVENT' | translate }}</span>
         </div>
-        <div nodeType="endEvent" class="item ui-draggable">
+        <div [attr.name]="'WORKFLOW.END_EVENT' | translate" nodeType="endEvent" class="item ui-draggable">
             <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
                 <g>
                     <path class="st0" d="M15,4c6.1,0,11,4.9,11,11s-4.9,11-11,11S4,21.1,4,15S8.9,4,15,4 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15
@@ -36,7 +36,7 @@
             </svg>
             <span>{{ 'WORKFLOW.END_EVENT' | translate }}</span>
         </div>
-        <div nodeType="intermediateCatchEvent" class="item ui-draggable">
+        <div [attr.name]="'WORKFLOW.TIMER_EVENT' | translate" nodeType="intermediateCatchEvent" class="item ui-draggable">
             <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
                 <g>
                     <path class="st0" d="M15,0C6.7,0,0,6.7,0,15c0,8.3,6.7,15,15,15c8.3,0,15-6.7,15-15C30,6.7,23.3,0,15,0z M16,27.9V26
         </div>
       -->
     </accordion-group>
-    <accordion-group [isOpen]="true" #task>
-        <div accordion-heading class="toolbar-head">
-            <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': task?.isOpen, 'fa-chevron-right': !task?.isOpen}"></i>
-            <i class="fa fa-th-list"></i>
-            <span>{{ 'WORKFLOW.BPMN_TASK' | translate }}</span>
-        </div>
-        <div *ngIf="!isCatalog" nodeType="toscaNodeManagementTask" class="item ui-draggable">
-            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
-                <g>
-                    <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3
-                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />
-                    <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />
-                    <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />
-                    <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />
-                    <path class="st0" d="M24.7,15.1h-5c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1h1.5v5.7c0,0.6,0.4,1,1,1s1-0.4,1-1v-5.7h1.5c0.6,0,1-0.4,1-1
-                        C25.7,15.5,25.2,15.1,24.7,15.1z" />
-                </g>
-            </svg>
-            <span>{{ 'WORKFLOW.TOSCA_TASK' | translate }}</span>
-        </div>
-        <div *ngIf="isCatalog" nodeType="restTask" class="item ui-draggable">
-            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
-                <g>
-                    <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3
-                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />
-                    <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />
-                    <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />
-                    <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />
-                    <path class="st0" d="M24.1,22.6l-1.6-2.7c0.9-0.4,1.5-1.2,1.5-2.2c0-1.4-1.2-2.5-2.8-2.5h-1.9c-0.2,0-0.4,0.1-0.6,0.2
-                        c-0.2,0.1-0.3,0.3-0.3,0.6v7c0,0.4,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8v-2.8h0.8l1.9,3.2c0.1,0.2,0.4,0.4,0.7,0.4
-                        c0.1,0,0.3,0,0.4-0.1C24.2,23.5,24.4,23,24.1,22.6z M20.1,16.8h1.2c0.6,0,1.2,0.4,1.2,0.9s-0.5,0.9-1.2,0.9h-1.2V16.8z"
-                    />
-                </g>
-            </svg>
-            <span>{{ 'WORKFLOW.REST_TASK' | translate }}</span>
-        </div>
-        <div nodeType="scriptTask" class="item ui-draggable">
-            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
-                <g>
-                    <path class="st0" d="M24,1H6C3.2,1,1,3.2,1,6v18c0,2.8,2.2,5,5,5h18c2.8,0,5-2.2,5-5V6C29,3.2,26.8,1,24,1z M16.9,3.4
-                        c0.5,0,0.9,0.2,1.3,0.5c0.4,0.4,0.5,0.8,0.5,1.3c0,0.5-0.2,0.9-0.5,1.3L17.7,7l-5.3,5.3c-0.2-0.6-0.5-1.2-0.9-1.6
-                        c-0.4-0.4-1-0.8-1.6-0.9l5.8-5.8C16,3.6,16.4,3.4,16.9,3.4z M10.3,27H6c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h8.2l-7.4,7.4
-                        c-0.1,0.1-0.2,0.2-0.3,0.3c-0.7,0.7-1,1.6-1,2.5c0,0.9,0.4,1.8,1,2.5l5.2,5.2l-1.3,1.3c-0.7,0.7-1,1.6-1,2.5
-                        C9.3,25.5,9.7,26.4,10.3,27z M14.1,25.9c-0.4,0.4-0.8,0.5-1.3,0.5c-0.5,0-0.9-0.2-1.3-0.5c-0.4-0.4-0.5-0.8-0.5-1.3
-                        c0-0.5,0.2-0.9,0.5-1.3l1.3-1.3l0.5,0.5l0.8,0.8c0.4,0.4,0.5,0.8,0.5,1.3C14.6,25.1,14.5,25.5,14.1,25.9z M14.5,21.3l-6.8-6.8
-                        c-0.4-0.4-0.5-0.8-0.5-1.3c0-0.5,0.2-0.9,0.5-1.3c0.4-0.4,0.8-0.5,1.3-0.5c0.5,0,0.9,0.2,1.3,0.5c0.4,0.4,0.5,0.8,0.5,1.3
-                        c0,0.5-0.2,0.9-0.5,1.3l0.9,0.9c0.2,0.2,0.4,0.2,0.6,0l5.2-5.2l4.4,4.4l0.8,0.8c0.4,0.4,0.5,0.8,0.5,1.3c0,0.5-0.2,0.9-0.5,1.3v0
-                        l-5.8,5.8c-0.1-0.6-0.5-1.2-0.9-1.6L14.5,21.3z M27,24c0,1.7-1.3,3-3,3h-8.6l7.9-7.9c0.7-0.7,1-1.6,1-2.5c0-0.9-0.4-1.8-1-2.5
-                        l-0.8-0.8L18.1,9l1.3-1.3c0.7-0.7,1-1.6,1-2.5c0-0.8-0.3-1.6-0.8-2.2H24c1.7,0,3,1.3,3,3V24z" />
-                    <path class="st0" d="M17.2,12.4c-0.3-0.3-0.8-0.3-1.1,0L12.6,16c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2
-                        l3.6-3.6C17.5,13.1,17.5,12.7,17.2,12.4z" />
-                    <path class="st0" d="M18.9,14.2c-0.3-0.3-0.8-0.3-1.1,0l-3.6,3.6c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2
-                        c0.2,0,0.4-0.1,0.5-0.2l3.6-3.6C19.2,14.9,19.2,14.4,18.9,14.2z" />
-                    <path class="st0" d="M17.1,20.6l3.6-3.6c0.3-0.3,0.3-0.8,0-1.1s-0.8-0.3-1.1,0L16,19.5c-0.3,0.3-0.3,0.8,0,1.1
-                        c0.1,0.1,0.3,0.2,0.5,0.2S17,20.7,17.1,20.6z" />
-                </g>
-            </svg>
-            <span>{{ 'WORKFLOW.SCRIPT_TASK' | translate }}</span>
-        </div>
-    </accordion-group>
     <accordion-group [isOpen]="true" #getway>
         <div accordion-heading class="toolbar-head">
             <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': getway?.isOpen, 'fa-chevron-right': !getway?.isOpen}"></i>
             <i class="fa fa-th-list"></i>
             <span>{{ 'WORKFLOW.BPMN_GETWAY' | translate }}</span>
         </div>
-        <div nodeType="exclusiveGateway" class="item ui-draggable">
+        <div [attr.name]="'WORKFLOW.EXCLUSIVE_GATEWAY' | translate" nodeType="exclusiveGateway" class="item ui-draggable">
             <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
                 <g>
                     <path class="st0" d="M16.4,15l3.2-3.2c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0L15,13.6l-3.2-3.2c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4
             </svg>
             <span>{{ 'WORKFLOW.EXCLUSIVE_GATEWAY' | translate }}</span>
         </div>
-        <div nodeType="parallelGateway" class="item ui-draggable">
+        <div [attr.name]="'WORKFLOW.PARALLEL_GATEWAY' | translate" nodeType="parallelGateway" class="item ui-draggable">
             <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
                 <g>
                     <path class="st0" d="M20.5,14H16V9.5c0-0.6-0.4-1-1-1s-1,0.4-1,1V14H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H14v4.5c0,0.6,0.4,1,1,1
             <span>{{ 'WORKFLOW.SUB_PROCESS' | translate }}</span>
         </div>
     </accordion-group> -->
+    <wfm-toolbar-node></wfm-toolbar-node>
 </accordion>
index 1242215..bfc4509 100644 (file)
@@ -12,7 +12,7 @@
 
 import { AfterViewChecked, Component, OnInit } from '@angular/core';
 
-import { DataService } from '../../services/data/data.service';
+import { SettingService } from '../../services/setting.service';
 import { BroadcastService } from '../../services/broadcast.service';
 import { JsPlumbService } from '../../services/jsplumb.service';
 
@@ -21,29 +21,10 @@ import { JsPlumbService } from '../../services/jsplumb.service';
  * The supported nodes can be dragged to container component. which will add a new node to the workflow.
  */
 @Component({
-    selector: 'b4t-toolbar',
+    selector: 'wfm-toolbar',
     templateUrl: 'toolbar.component.html',
     styleUrls: ['./toolbar.component.css']
 })
-export class ToolbarComponent implements AfterViewChecked, OnInit {
-    public isCatalog = true;
-    private needInitButton = false;
+export class ToolbarComponent {
 
-    constructor(private jsPlumbService: JsPlumbService, private broadcastService: BroadcastService,
-        private dataService: DataService) { }
-
-    public ngOnInit() {
-        this.broadcastService.backendServiceReady$.subscribe(() => {
-            this.isCatalog = 'Catalog' === this.dataService.getBackendType();
-            this.needInitButton = true;
-        });
-    }
-
-    public ngAfterViewChecked() {
-        if (this.needInitButton) {
-            this.jsPlumbService.buttonDraggable();
-            this.jsPlumbService.buttonDroppable();
-            this.needInitButton = false;
-        }
-    }
 }
diff --git a/sdc-workflow-designer-ui/src/app/model/model.ts b/sdc-workflow-designer-ui/src/app/model/model.ts
new file mode 100644 (file)
index 0000000..bd3c2c6
--- /dev/null
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { WorkflowNode } from './workflow/workflow-node';
+export class Model {
+    public nodes: WorkflowNode[] = [];
+    public configs: any = {};
+}
index 5ea6005..417f79c 100644 (file)
@@ -1,3 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
 export enum NoticeType {
     success, info, warning, danger
 }
index 9897f70..7246e1c 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 import { WorkflowNode } from './workflow/workflow-node';
+import { Model } from './model';
 
 export class PlanModel {
-    public nodes: WorkflowNode[] = [];
-    public configs: any = {};
+    public id: string;
+    public name: string;
+    public version: string;
+    public description: string;
+    public scene: string;
+    public data = new Model();
 }
index 9101bce..cace1c4 100644 (file)
@@ -1,17 +1,17 @@
-/**\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- */\r
-import { Swagger } from './swagger';\r
-\r
-export class RestConfig {\r
-    constructor(public id: string, public name: string, public version: string, public url: string, public definition: string,\r
-        public swagger?: Swagger) { }\r
-}\r
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { Swagger } from './swagger';
+
+export class RestConfig {
+    constructor(public id: string, public name: string, public version: string, public url: string,
+        public swagger?: Swagger) { }
+}
index e0ed149..1886708 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
 
-export class SwaggerParameter {
+export class SwaggerParameterClass {
     public description: string;
     public position: string;  // in path, query, header, body, form
     public name: string;
     public required: boolean;
     public type: string;
+    public enum: any[];
 
     // if position is body
     public schema: SwaggerSchemaObject;
@@ -26,6 +27,7 @@ export class SwaggerParameter {
         this.name = options.name;
         this.required = options.required;
         this.type = options.type;
+        this.enum = options.enum;
         if (this.position === 'body') {
             this.schema = getSchemaObject(options.schema);
         }
@@ -40,7 +42,7 @@ export class SwaggerHeader {
     }
 }
 
-export class SwaggerResponse {
+export class SwaggerResponseClass {
     public description: string;
     public schema: SwaggerSchemaObject;
     public headers: any;
@@ -65,7 +67,7 @@ export class SwaggerMethod {
     public consumes: string[];
     public description: string;
     public operationId: string;
-    public parameters: SwaggerParameter[];
+    public parameters: SwaggerParameterClass[];
     public produces: string[];
     public responses: any;
     public summary: string;
@@ -75,7 +77,7 @@ export class SwaggerMethod {
         this.consumes = consumes;
         this.description = description;
         this.operationId = operationId;
-        this.parameters = parameters.map(param => new SwaggerParameter(param));
+        this.parameters = parameters.map(param => new SwaggerParameterClass(param));
         this.produces = produces;
         this.responses = this.initResponses(responses);
         this.summary = summary;
@@ -85,7 +87,7 @@ export class SwaggerMethod {
     private initResponses(responses: any): any {
         const responseObjs = {};
         for (const key in responses) {
-            responseObjs[key] = new SwaggerResponse(responses[key]);
+            responseObjs[key] = new SwaggerResponseClass(responses[key]);
         }
 
         return responseObjs;
@@ -189,7 +191,7 @@ export class SwaggerReferenceObject extends SwaggerSchemaObject {
 
 export class SwaggerPrimitiveObject extends SwaggerSchemaObject {
     public collectionFormat: string;
-    public defaultValue: any;
+    public default: any;
     public enumValues: any[];
     public exclusiveMaximum: boolean;
     public exclusiveMinimum: boolean;
@@ -205,7 +207,7 @@ export class SwaggerPrimitiveObject extends SwaggerSchemaObject {
     constructor(options: any) {
         super();
         this.collectionFormat = options.collectionFormat;
-        this.defaultValue = options.default;
+        this.default = options.default;
         this.enumValues = options.enum;
         this.exclusiveMaximum = options.exclusiveMaximum;
         this.exclusiveMinimum = options.exclusiveMinimum;
diff --git a/sdc-workflow-designer-ui/src/app/model/value-object.ts b/sdc-workflow-designer-ui/src/app/model/value-object.ts
new file mode 100644 (file)
index 0000000..0a079a8
--- /dev/null
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+export interface ValueObject {
+    value?: any;
+    valueSource: string;
+}
index f76f659..720185a 100644 (file)
  *******************************************************************************/
 
 export enum ValueSource {
-    String,
+    integer,
+    number,
+    boolean,
+    string,
     Plan,
     Topology,
     Variable,
index ab6d07b..d305696 100644 (file)
  *******************************************************************************/
 
 export enum ValueType {
-    String,
-    Number,
-    Date,
+    integer,
+    number,
+    boolean,
+    string,
+    array,
+    object
 }
index 22170c1..c02816e 100644 (file)
@@ -15,11 +15,13 @@ export enum NodeType {
     endEvent,
     errorStartEvent,
     errorEndEvent,
+    intermediateCatchEvent,
     toscaNodeManagementTask,
+    serviceTask,
+    scriptTask,
     restTask,
     exclusiveGateway,
     parallelGateway,
     subProcess,
-    intermediateCatchEvent,
-    scriptTask
+    callActivity
 }
index 67ca7f3..7a90400 100644 (file)
@@ -14,7 +14,8 @@ import { ValueSource } from '../value-source.enum';
 import { ValueType } from '../value-type.enum';
 
 export class Parameter {
-    constructor(public name: string, public value: string, public valueSource: string,
-                public type: string = ValueType[ValueType.String], public required: boolean = false) {
+    constructor(public name: string, public value: any, public valueSource: string,
+        public type = ValueType[ValueType.string], public required = false,
+        public show = true, public errorMsg = '') {
     }
 }
index 12637d0..1235a47 100644 (file)
@@ -9,17 +9,21 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  */
-import { SwaggerResponse } from "../swagger";
+import { SwaggerResponseClass } from "../swagger";
 import { RestParameter } from './rest-parameter';
 import { WorkflowNode } from './workflow-node';
+import { SwaggerBaseParameter } from "./swagger/swagger-base-parameter";
 
 export interface RestTask extends WorkflowNode {
     restConfigId?: string;
+    baseUrl?: string;
+    serviceName?: string;
+    serviceVersion?: string;
     path?: string;
     method?: string;
     operationId?: string;
-    produces?: string[];
+    produces?: string[];        // do not support non json MIME types, maybe use this later.
     consumes?: string[];
-    parameters?: RestParameter[];
-    responses?: SwaggerResponse[];
+    parameters?: any[];
+    responses?: SwaggerResponseClass[];
 }
index 880f38a..75d86f5 100644 (file)
@@ -13,5 +13,5 @@ import { WorkflowNode } from './workflow-node';
 
 export interface ScriptTask extends WorkflowNode {
     scriptFormat: string;
-    script?: string;
+    script: string;
 }
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/service-task.ts b/sdc-workflow-designer-ui/src/app/model/workflow/service-task.ts
new file mode 100644 (file)
index 0000000..c0ce641
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { WorkflowNode } from './workflow-node';
+import { Parameter } from './parameter';
+
+export interface ServiceTask extends WorkflowNode {
+    className: string;
+    inputs: Parameter[];
+    outputs: Parameter[];
+}
index 628148a..f278d18 100644 (file)
@@ -17,7 +17,9 @@ export interface WorkflowNode extends WorkflowElement {
     connection: SequenceFlow[];
     id: string;
     name: string;
+    icon?: string;
     parentId: string;
     position: Position;
     type: string;
+    typeId?: string;
 }
diff --git a/sdc-workflow-designer-ui/src/app/services/auth.service.spec.ts b/sdc-workflow-designer-ui/src/app/services/auth.service.spec.ts
new file mode 100644 (file)
index 0000000..9bd500e
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { TestBed, inject } from '@angular/core/testing';
+
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      providers: [AuthService]
+    });
+  });
+
+  it('should be created', inject([AuthService], (service: AuthService) => {
+    expect(service).toBeTruthy();
+  }));
+});
diff --git a/sdc-workflow-designer-ui/src/app/services/auth.service.ts b/sdc-workflow-designer-ui/src/app/services/auth.service.ts
new file mode 100644 (file)
index 0000000..a8e6075
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { Injectable } from '@angular/core';
+import { Http } from '@angular/http';
+import { BroadcastService } from './broadcast.service';
+
+@Injectable()
+export class AuthService {
+  private static AuthUrl = "/api/oauth2/v1/perms/user/operations";
+  private static AllOperations = ["operation.apds.create", "operation.apds.delete", "operation.apds.modify",
+    "operation.apds.view", "operation.apds.import", "operation.apds.export", "operation.apds.deploy",
+    "operation.apds.test"];
+  private static ModifyOperation = 'operation.apds.modify';
+
+  constructor(private http: Http, private broadcastService: BroadcastService) {
+    this.checkRights();
+    // keep alive
+    // setInterval(() => {
+    //   console.log(`Keep session alive. Request per 3 minutes. ${new Date()}`);
+    //   this.checkRights();
+    // }, 180000);
+  }
+  public checkRights() {
+    // let data = { operations: AuthService.AllOperations };
+    // this.http.post(AuthService.AuthUrl, data).subscribe(res => {
+    //   let hasRightOP = res.json().operations;
+    //   if (hasRightOP.length > 0) {
+    //     this.broadcastService.broadcast(this.broadcastService.openRight, true);
+    //     if (hasRightOP.indexOf(AuthService.ModifyOperation) > -1) {
+    //       this.broadcastService.broadcast(this.broadcastService.saveRight, true);
+    //     } else {
+    //       this.broadcastService.broadcast(this.broadcastService.saveRight, false);
+    //     }
+    //   } else {
+    //     this.broadcastService.broadcast(this.broadcastService.openRight, false);
+    //     this.broadcastService.broadcast(this.broadcastService.saveRight, false);
+    //   }
+    // }, error => {
+    //   switch (error.status) {
+    //     // Incase oauth service not exists or operation set not exists
+    //     case 404:
+    //     case 501:
+    //     case 502:
+    //       this.broadcastService.broadcast(this.broadcastService.openRight, true);
+    //       this.broadcastService.broadcast(this.broadcastService.saveRight, true);
+    //       break;
+    //     default:
+    //       this.broadcastService.broadcast(this.broadcastService.openRight, false);
+    //       this.broadcastService.broadcast(this.broadcastService.saveRight, false);
+    //       break;
+    //   }
+    // });
+    this.broadcastService.broadcast(this.broadcastService.openRight, true);
+    this.broadcastService.broadcast(this.broadcastService.saveRight, true);
+  }
+}
index 6d80e91..410ae9b 100644 (file)
@@ -26,56 +26,38 @@ import { WorkflowElement } from '../model/workflow/workflow-element';
  */
 @Injectable()
 export class BroadcastService {
+    public openRight = new Subject<boolean>();
+    public openRight$ = this.openRight.asObservable();
 
-    public showProperty = new Subject<WorkflowElement>();
-    public showProperty$ = this.showProperty.asObservable();
+    public saveRight = new Subject<boolean>();
+    public saveRight$ = this.saveRight.asObservable();
 
-    public workflows = new Subject<Map<string, any>>();
-    public workflows$ = this.workflows.asObservable();
+    public initModel = new Subject<PlanModel>();
+    public initModel$ = this.initModel.asObservable();
 
-    public planId = new Subject<string>();
-    public planId$ = this.planId.asObservable();
+    public showProperty = new Subject<WorkflowElement>();
+    public showProperty$ = this.showProperty.asObservable();
 
     public planModel = new Subject<PlanModel>();
     public planModel$ = this.planModel.asObservable();
 
+    public updateModelToscaConfig = new Subject<any[]>();
+    public updateModelToscaConfig$ = this.updateModelToscaConfig.asObservable();
+
     public updateModelRestConfig = new Subject<RestConfig[]>();
     public updateModelRestConfig$ = this.updateModelRestConfig.asObservable();
 
-    public saveEvent = new Subject<any>();
+    public updateNodeTypeConfig = new Subject<any[]>();
+    public updateNodeTypeConfig$ = this.updateNodeTypeConfig.asObservable();
+
+    public saveEvent = new Subject<PlanModel>();
     public saveEvent$ = this.saveEvent.asObservable();
 
     public selectedElement = new Subject<WorkflowElement[]>();
     public selectedElement$ = this.selectedElement.asObservable();
 
-    // public elementClick = new Subject<WorkflowElement>();
-    // public elementClick$ = this.elementClick.asObservable();
-    /**
-     * this should be used while the source of rest interfaces changed.
-     * @type {Subject<>}
-     */
-    public backendServiceReady = new Subject<any>();
-    public backendServiceReady$ = this.backendServiceReady.asObservable();
-
-
-    public nodeProperty = new Subject<WorkflowNode>();
-    public nodeProperty$ = this.nodeProperty.asObservable();
-
-    public nodeTaskChange = new Subject<WorkflowNode>();
-    public nodeTaskChange$ = this.nodeTaskChange.asObservable();
-
-    public showSequenceFlow = new Subject<boolean>();
-    public showSequenceFlow$ = this.showSequenceFlow.asObservable();
-
-    public sequenceFlow = new Subject<SequenceFlow>();
-    public sequenceFlow$ = this.sequenceFlow.asObservable();
-
-    public currentSequenceFlow = new Subject<SequenceFlow>();
-    public currentSequenceFlow$ = this.currentSequenceFlow.asObservable();
-    public currentWorkflowNode = new Subject<WorkflowNode>();
-    public currentWorkflowNode$ = this.currentWorkflowNode.asObservable();
-    public currentType = new Subject<string>();
-    public currentType$ = this.currentType.asObservable();
+    public swagger = new Subject<any>();
+    public swagger$ = this.swagger.asObservable();
 
     /**
      * broadcast datas
diff --git a/sdc-workflow-designer-ui/src/app/services/data/backend.service.ts b/sdc-workflow-designer-ui/src/app/services/data/backend.service.ts
deleted file mode 100644 (file)
index 41f6fcc..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * Copyright (c) 2017 ZTE Corporation.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and the Apache License 2.0 which both accompany this distribution,
- * and are available at http://www.eclipse.org/legal/epl-v10.html
- * and http://www.apache.org/licenses/LICENSE-2.0
- *
- * Contributors:
- *     ZTE - initial API and implementation and/or initial documentation
- */
-
-import { Injectable } from '@angular/core';
-import { Observable } from 'rxjs/Observable';
-import { TranslateService } from '@ngx-translate/core';
-
-import { PlanModel } from '../../model/plan-model';
-import { NodeTemplate } from '../../model/topology/node-template';
-import { HttpService } from '../../util/http.service';
-import { BroadcastService } from '../broadcast.service';
-import { NoticeService } from '../notice.service';
-
-/**
- * BackendService
- * provides backend data accessor to load and save data.
- */
-@Injectable()
-export abstract class BackendService {
-    private topologyProperties: { name: string, value: string }[] = [];
-
-    constructor(protected broadcastService: BroadcastService, protected noticeService: NoticeService,
-        protected httpService: HttpService, private translate: TranslateService) {
-        this.broadcastService.saveEvent$.subscribe(data => {
-            this.save(data).subscribe(response => {
-                this.translate.get('WORKFLOW.MSG.SAVE_SUCCESS').subscribe((res: string) => {
-                    this.noticeService.success(res);
-                });
-            }, error => {
-                this.noticeService.error(error);
-            });
-        });
-    }
-
-    public abstract loadPlans(): Observable<Map<number, any>>;
-
-    public abstract getBackendType(): string;
-
-    public abstract setParameters(params: any);
-
-    public abstract loadNodeTemplates(): Observable<NodeTemplate[]>;
-
-    public abstract loadTopologyProperties(nodeTemplate: NodeTemplate): Observable<string[]>;
-
-    public abstract loadNodeTemplateInterfaces(nodeTemplate: NodeTemplate): Observable<string[]>;
-
-    public abstract loadNodeTemplateOperations(nodeTemplate: NodeTemplate,
-        interfaceName: string): Observable<string[]>;
-
-    public abstract loadNodeTemplateOperationParameter(nodeTemplate: NodeTemplate,
-        interfaceName: string,
-        operation: string): Observable<any>;
-
-    public abstract save(data: any): Observable<any>;
-
-    public abstract loadPlan(): Observable<PlanModel>;
-
-    public getTopologyProperties(): { name: string, value: string }[] {
-        return this.topologyProperties;
-    }
-
-    public canEdit(): boolean {
-        return true;
-    }
-
-    protected refreshTopologyProperties(): void {
-        this.loadNodeTemplates().subscribe(nodes => {
-            if (0 === nodes.length) {
-                return;
-            }
-
-            const subscribes = nodes.map(node => this.loadTopologyProperties(node));
-            Observable.forkJoin(subscribes).map(nodesProperties => {
-                const allProperties: { name: string, value: string }[] = [];
-                nodesProperties.forEach((properties, index) => {
-                    properties.forEach(property => {
-                        // allProperties.push(nodes[index].name + '.' + property);
-                        const propertyOption = {
-                            name: `${nodes[index].name}.${property}`,
-                            value: `[${nodes[index].name}].[${property}]`
-                        };
-                        allProperties.push(propertyOption);
-                    });
-                });
-                return allProperties;
-            }).subscribe(allProperties => {
-                this.topologyProperties = allProperties;
-            });
-        });
-    }
-}
diff --git a/sdc-workflow-designer-ui/src/app/services/data/data.service.ts b/sdc-workflow-designer-ui/src/app/services/data/data.service.ts
deleted file mode 100644 (file)
index 73be01b..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Copyright (c) 2017 ZTE Corporation.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and the Apache License 2.0 which both accompany this distribution,
- * and are available at http://www.eclipse.org/legal/epl-v10.html
- * and http://www.apache.org/licenses/LICENSE-2.0
- *
- * Contributors:
- *     ZTE - initial API and implementation and/or initial documentation
- */
-
-import { Injectable } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
-import { Observable } from 'rxjs/Observable';
-import { TranslateService } from '@ngx-translate/core';
-
-import { PlanModel } from '../../model/plan-model';
-import { NodeTemplate } from '../../model/topology/node-template';
-import { HttpService } from '../../util/http.service';
-import { BroadcastService } from '../broadcast.service';
-import { SettingService } from "../setting.service";
-import { NoticeService } from '../notice.service';
-import { BackendService } from './backend.service';
-import { SdcService } from './sdc.service';
-
-/**
- * DataService
- * BackendService factory, provide backend service by running environment.
- */
-@Injectable()
-export class DataService {
-    private service: BackendService;
-
-    constructor(private broadcastService: BroadcastService, private noticeService: NoticeService,
-        protected httpService: HttpService, private translate: TranslateService,
-        private settingService: SettingService, private activatedRoute: ActivatedRoute) {
-        this.createBackendService();
-    }
-
-    public initData(): void {
-        this.activatedRoute.queryParams.subscribe(queryParams => {
-            this.service.setParameters(queryParams);
-        });
-    }
-
-    public getTopologyProperties(): { name: string, value: string }[] {
-        return this.service.getTopologyProperties();
-    }
-
-    public loadNodeTemplates(): Observable<NodeTemplate[]> {
-        return this.service.loadNodeTemplates();
-    }
-
-    public loadNodeTemplateInterfaces(nodeTemplate: NodeTemplate): Observable<string[]> {
-        return this.service.loadNodeTemplateInterfaces(nodeTemplate);
-    }
-
-    public loadNodeTemplateOperations(nodeTemplate: NodeTemplate, interfaceName: string): Observable<string[]> {
-        return this.service.loadNodeTemplateOperations(nodeTemplate, interfaceName);
-    }
-
-    public loadNodeTemplateOperationParameter(nodeTemplate: NodeTemplate, interfaceName: string,
-        operation: string): Observable<any> {
-        return this.service.loadNodeTemplateOperationParameter(nodeTemplate, interfaceName, operation);
-    }
-
-    public getBackendType(): string {
-        return this.service.getBackendType();
-    }
-
-    private createBackendService() {
-        this.settingService.getSetting().subscribe(response => {
-            let serviceType = response.BackendType;
-            this.service = new SdcService(this.broadcastService, this.noticeService, this.httpService, this.translate);
-            this.broadcastService.broadcast(this.broadcastService.backendServiceReady, null);
-        })
-    }
-}
diff --git a/sdc-workflow-designer-ui/src/app/services/data/in-memory-data.service.ts b/sdc-workflow-designer-ui/src/app/services/data/in-memory-data.service.ts
deleted file mode 100644 (file)
index a744918..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/**\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- */\r
-\r
-import { Injectable } from '@angular/core';\r
-import { InMemoryDbService } from 'angular-in-memory-web-api';\r
-import { workflowFJH } from "./mockdata";\r
-import { PlanModel } from '../../model/plan-model';\r
-/**\r
- * InMemeoryDataService\r
- * Mock backend data\r
- */\r
-export class InMemoryDataService implements InMemoryDbService {\r
-    createDb() {\r
-\r
-        const swagger = {"swagger":"2.0","info":{"version":"1.0.0","title":"MicroService Bus rest API"},"basePath":"/api/microservices/v1","tags":[{"name":"metrics"},{"name":"iuiRoute"},{"name":"ServiceAccess"},{"name":"ApiRoute"},{"name":"MSB-Service Resource"},{"name":"CustomRoute"}],"paths":{"/apiRoute":{"get":{"tags":["ApiRoute"],"summary":"get all ApiRoute ","description":"","operationId":"getApiRoutes","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/ApiRouteInfo"}}},"500":{"description":"get ApiRouteInfo List  fail","schema":{"type":"string"}}}},"post":{"tags":["ApiRoute"],"summary":"add one ApiRoute ","description":"","operationId":"addApiRoute","produces":["application/json"],"parameters":[{"in":"body","name":"body","description":"ApiRoute Instance Info","required":true,"schema":{"$ref":"#/definitions/ApiRouteInfo"}}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiRouteInfo"}},"400":{"description":"Unprocessable ApiRouteInfo JSON REQUEST","schema":{"type":"string"}},"500":{"description":"add ApiRouteInfo fail","schema":{"type":"string"}},"415":{"description":"Unprocessable ApiRouteInfo Entity ","schema":{"type":"string"}}}}},"/apiRoute/apiDocs":{"get":{"tags":["ApiRoute"],"summary":"get all Local apiDoc ","description":"","operationId":"getApiDocs","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"type":"string"}}},"500":{"description":"get apiDoc List  fail","schema":{"type":"string"}}}}},"/apiRoute/apiGatewayPort":{"get":{"tags":["ApiRoute"],"summary":"get apiGateway Port ","description":"","operationId":"getApiGatewayPort","produces":["text/plain"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"string"}},"500":{"description":"get apiGateway Port  fail","schema":{"type":"string"}}}}},"/apiRoute/discoverInfo":{"get":{"tags":["ApiRoute"],"summary":"get discover Info ","description":"","operationId":"getServiceDiscoverInfo","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/DiscoverInfo"}},"500":{"description":"get discover Info fail","schema":{"type":"string"}}}}},"/apiRoute/export":{"get":{"tags":["ApiRoute"],"summary":"export all route service Info by json-file","description":"","operationId":"exportService","produces":["text/plain"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"string"}},"500":{"description":"export fail","schema":{"type":"string"}},"406":{"description":" not Acceptable client-side","schema":{"type":"string"}}}}},"/apiRoute/{serviceName}/version/{version}":{"get":{"tags":["ApiRoute"],"summary":"get one ApiRoute ","description":"","operationId":"getApiRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"ApiRoute serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"ApiRoute version,if the version is empty, please enter \"null\"","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiRouteInfo"}},"500":{"description":"get ApiRouteInfo fail","schema":{"type":"string"}},"404":{"description":"ApiRouteInfo not found","schema":{"type":"string"}},"415":{"description":"Unprocessable ApiRouteInfo Entity ","schema":{"type":"string"}}}},"put":{"tags":["ApiRoute"],"summary":"update one ApiRoute by serviceName and version","description":"","operationId":"updateApiRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"ApiRoute serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"ApiRoute version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"in":"body","name":"body","description":"ApiRoute Instance Info","required":true,"schema":{"$ref":"#/definitions/ApiRouteInfo"}}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiRouteInfo"}},"400":{"description":"Unprocessable ApiRouteInfo JSON REQUEST","schema":{"type":"string"}},"500":{"description":"update ApiRouteInfo fail","schema":{"type":"string"}},"415":{"description":"Unprocessable ApiRouteInfo Entity ","schema":{"type":"string"}}}},"delete":{"tags":["ApiRoute"],"summary":"delete one ApiRoute by serviceName and version","description":"","operationId":"deleteApiRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"ApiRoute serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"ApiRoute version,if the version is empty, please enter \"null\"","required":true,"type":"string"}],"responses":{"500":{"description":"delete ApiRouteInfo fail","schema":{"type":"string"}},"204":{"description":"delete ApiRouteInfo succeed "},"404":{"description":"ApiRouteInfo not found","schema":{"type":"string"}}}}},"/apiRoute/{serviceName}/version/{version}/status/{status}":{"put":{"tags":["ApiRoute"],"summary":"update one ApiRoute  status by serviceName and version","description":"","operationId":"updateApiRouteStatus","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"ApiRoute serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"ApiRoute version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"name":"status","in":"path","description":"ApiRoute status,1:abled  0:disabled","required":true,"type":"string"}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiRouteInfo"}},"500":{"description":"update status fail","schema":{"type":"string"}},"415":{"description":"Unprocessable ApiRouteInfo Entity ","schema":{"type":"string"}},"404":{"description":"ApiRouteInfo not found","schema":{"type":"string"}}}}},"/customRoute/all":{"get":{"tags":["CustomRoute"],"summary":"get all CustomRoute ","description":"","operationId":"getCustomRoutes","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/CustomRouteInfo"}}},"500":{"description":"get CustomRouteInfo List  fail","schema":{"type":"string"}}}}},"/customRoute/instance":{"get":{"tags":["CustomRoute"],"summary":"get one CustomRoute ","description":"","operationId":"getCustomRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"query","description":"CustomRoute serviceName","required":false,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/CustomRouteInfo"}},"500":{"description":"get CustomRoute fail","schema":{"type":"string"}},"404":{"description":"CustomRoute not found","schema":{"type":"string"}},"415":{"description":"Unprocessable CustomRoute Entity ","schema":{"type":"string"}}}},"post":{"tags":["CustomRoute"],"summary":"add one CustomRoute ","description":"","operationId":"addCustomRoute","produces":["application/json"],"parameters":[{"in":"body","name":"body","description":"CustomRoute Instance Info","required":true,"schema":{"$ref":"#/definitions/CustomRouteInfo"}}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/CustomRouteInfo"}},"400":{"description":"Unprocessable CustomRouteInfo JSON REQUEST","schema":{"type":"string"}},"500":{"description":"add CustomRouteInfo fail","schema":{"type":"string"}},"415":{"description":"Unprocessable CustomRouteInfo Entity ","schema":{"type":"string"}}}},"put":{"tags":["CustomRoute"],"summary":"update one CustomRoute by serviceName","description":"","operationId":"updateCustomRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"query","description":"CustomRoute serviceName","required":true,"type":"string"},{"in":"body","name":"body","description":"CustomRoute Instance Info","required":true,"schema":{"$ref":"#/definitions/CustomRouteInfo"}}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/CustomRouteInfo"}},"400":{"description":"Unprocessable CustomRoute JSON REQUEST","schema":{"type":"string"}},"500":{"description":"update CustomRoute fail","schema":{"type":"string"}},"415":{"description":"Unprocessable CustomRoute Entity ","schema":{"type":"string"}}}},"delete":{"tags":["CustomRoute"],"summary":"delete one CustomRoute by serviceName","description":"","operationId":"deleteCustomRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"query","description":"CustomRoute serviceName","required":true,"type":"string"}],"responses":{"500":{"description":"delete customRoute fail","schema":{"type":"string"}},"204":{"description":"delete customRoute succeed "},"404":{"description":"customRoute not found","schema":{"type":"string"}}}}},"/customRoute/status":{"put":{"tags":["CustomRoute"],"summary":"update one CustomRoute  status by serviceName ","description":"","operationId":"updateCustomRouteStatus","produces":["application/json"],"parameters":[{"name":"serviceName","in":"query","description":"CustomRoute serviceName","required":true,"type":"string"},{"name":"status","in":"query","description":"CustomRoute status,1:abled  0:disabled","required":true,"type":"string"}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/CustomRouteInfo"}},"500":{"description":"update status fail","schema":{"type":"string"}},"415":{"description":"Unprocessable customRoute Entity ","schema":{"type":"string"}},"404":{"description":"customRoute not found","schema":{"type":"string"}}}}},"/iuiRoute":{"get":{"tags":["iuiRoute"],"summary":"get all iuiRoute ","description":"","operationId":"getIuiRoutes","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/IuiRouteInfo"}}},"500":{"description":"get iuiRouteInfo List  fail","schema":{"type":"string"}}}},"post":{"tags":["iuiRoute"],"summary":"add one iuiRoute ","description":"","operationId":"addIuiRoute","produces":["application/json"],"parameters":[{"in":"body","name":"body","description":"iuiRoute Instance Info","required":true,"schema":{"$ref":"#/definitions/IuiRouteInfo"}}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/IuiRouteInfo"}},"400":{"description":"Unprocessable iuiRouteInfo JSON REQUEST","schema":{"type":"string"}},"500":{"description":"add iuiRouteInfo fail","schema":{"type":"string"}},"415":{"description":"Unprocessable iuiRouteInfo Entity ","schema":{"type":"string"}}}}},"/iuiRoute/{serviceName}":{"get":{"tags":["iuiRoute"],"summary":"get one iuiRoute ","description":"","operationId":"getIuiRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"iuiRoute serviceName","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/IuiRouteInfo"}},"500":{"description":"get IuiRouteInfo fail","schema":{"type":"string"}},"404":{"description":"IuiRouteInfo not found","schema":{"type":"string"}},"415":{"description":"Unprocessable IuiRouteInfo Entity ","schema":{"type":"string"}}}},"put":{"tags":["iuiRoute"],"summary":"update one iuiRoute by serviceName","description":"","operationId":"updateIuiRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"iuiRoute serviceName","required":true,"type":"string"},{"in":"body","name":"body","description":"iuiRoute Instance Info","required":true,"schema":{"$ref":"#/definitions/IuiRouteInfo"}}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/IuiRouteInfo"}},"400":{"description":"Unprocessable IuiRouteInfo JSON REQUEST","schema":{"type":"string"}},"500":{"description":"update IuiRouteInfo fail","schema":{"type":"string"}},"415":{"description":"Unprocessable IuiRouteInfo Entity ","schema":{"type":"string"}}}},"delete":{"tags":["iuiRoute"],"summary":"delete one iuiRoute by serviceName","description":"","operationId":"deleteIuiRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"iuiRoute serviceName","required":true,"type":"string"}],"responses":{"500":{"description":"delete IuiRouteInfo fail","schema":{"type":"string"}},"204":{"description":"delete IuiRouteInfo succeed "},"404":{"description":"IuiRouteInfo not found","schema":{"type":"string"}}}}},"/iuiRoute/{serviceName}/status/{status}":{"put":{"tags":["iuiRoute"],"summary":"update one iuiRoute  status by serviceName ","description":"","operationId":"updateIuiRouteStatus","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"iuiRoute serviceName","required":true,"type":"string"},{"name":"status","in":"path","description":"iuiRoute status,1:abled  0:disabled","required":true,"type":"string"}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/IuiRouteInfo"}},"500":{"description":"update IuiRouteInfo status fail","schema":{"type":"string"}},"415":{"description":"Unprocessable IuiRouteInfo Entity ","schema":{"type":"string"}},"404":{"description":"IuiRouteInfo not found","schema":{"type":"string"}}}}},"/metrics":{"get":{"tags":["metrics"],"summary":"get Metrics Info ","description":"","operationId":"getMetricsInfo","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/MetricsInfo"}}}}},"/serviceaccess/{serviceName}":{"get":{"tags":["ServiceAccess"],"summary":"get the msb access address of the service ","description":"","operationId":"getApiRoute","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"serviceName","required":true,"type":"string"},{"name":"type","in":"query","description":"service type","required":false,"type":"string","enum":["api","iui","custom","p2p"]},{"name":"version","in":"query","description":"version","required":false,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ServiceAccessInfo"}},"500":{"description":"get access address error "}}}},"/services":{"get":{"tags":["MSB-Service Resource"],"summary":"get all microservices ","description":"","operationId":"getMicroService","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/MicroServiceFullInfo"}}},"500":{"description":"get microservice List  fail","schema":{"type":"string"}}}},"post":{"tags":["MSB-Service Resource"],"summary":"add one microservice ","description":"","operationId":"addMicroService","produces":["application/json"],"parameters":[{"in":"body","name":"body","description":"MicroServiceInfo Instance Info","required":true,"schema":{"$ref":"#/definitions/MicroServiceInfo"}},{"name":"createOrUpdate","in":"query","description":"createOrUpdate","required":false,"type":"boolean","default":"true"},{"name":"port","in":"query","description":"port","required":false,"type":"string"}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/MicroServiceFullInfo"}},"400":{"description":"Unprocessable MicroServiceInfo JSON REQUEST","schema":{"type":"string"}},"500":{"description":"add microservice fail","schema":{"type":"string"}},"415":{"description":"Unprocessable MicroServiceInfo Entity ","schema":{"type":"string"}}}}},"/services/{serviceName}/version/{version}":{"get":{"tags":["MSB-Service Resource"],"summary":"get one microservice ","description":"","operationId":"getMicroService","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"microservice serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"microservice version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"name":"port","in":"query","description":"port","required":false,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/MicroServiceFullInfo"}},"500":{"description":"get microservice fail","schema":{"type":"string"}},"404":{"description":"microservice not found","schema":{"type":"string"}},"415":{"description":"Unprocessable MicroServiceInfo Entity ","schema":{"type":"string"}}}},"put":{"tags":["MSB-Service Resource"],"summary":"update one microservice by serviceName and version","description":"","operationId":"updateMicroService","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"microservice serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"microservice version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"in":"body","name":"body","description":"microservice Instance Info","required":true,"schema":{"$ref":"#/definitions/MicroServiceInfo"}}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/MicroServiceFullInfo"}},"400":{"description":"Unprocessable MicroServiceInfo JSON REQUEST","schema":{"type":"string"}},"500":{"description":"update microservice fail","schema":{"type":"string"}},"415":{"description":"Unprocessable MicroServiceInfo Entity ","schema":{"type":"string"}}}},"delete":{"tags":["MSB-Service Resource"],"summary":"delete one full microservice by serviceName and version","description":"","operationId":"deleteMicroService","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"microservice serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"microservice version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"name":"port","in":"query","description":"port","required":false,"type":"string"}],"responses":{"500":{"description":"delete microservice fail","schema":{"type":"string"}},"204":{"description":"delete microservice succeed "},"404":{"description":"microservice not found","schema":{"type":"string"}},"415":{"description":"Unprocessable MicroServiceInfo Entity ","schema":{"type":"string"}}}}},"/services/{serviceName}/version/{version}/nodes/{ip}/{port}":{"put":{"tags":["MSB-Service Resource"],"summary":"update  single node by serviceName and version and node","description":"","operationId":"updateNode","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"microservice serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"microservice version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"name":"ip","in":"path","description":"ip","required":true,"type":"string"},{"name":"port","in":"path","description":"port","required":true,"type":"string"},{"name":"ttl","in":"query","description":"ttl","required":false,"type":"integer","format":"int32"}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/MicroServiceFullInfo"}},"500":{"description":"update node fail","schema":{"type":"string"}},"415":{"description":"Unprocessable MicroServiceInfo Entity ","schema":{"type":"string"}},"404":{"description":"microservice not found","schema":{"type":"string"}}}},"delete":{"tags":["MSB-Service Resource"],"summary":"delete single node by serviceName and version and node","description":"","operationId":"deleteNode","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"microservice serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"microservice version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"name":"ip","in":"path","description":"ip","required":true,"type":"string"},{"name":"port","in":"path","description":"port","required":true,"type":"string"}],"responses":{"500":{"description":"delete node fail","schema":{"type":"string"}},"204":{"description":"delete node succeed "},"404":{"description":"node not found","schema":{"type":"string"}},"415":{"description":"Unprocessable MicroServiceInfo Entity ","schema":{"type":"string"}}}}},"/services/{serviceName}/version/{version}/status/{status}":{"put":{"tags":["MSB-Service Resource"],"summary":"update  microservice status by serviceName and version","description":"","operationId":"updateServiceStatus","produces":["application/json"],"parameters":[{"name":"serviceName","in":"path","description":"microservice serviceName","required":true,"type":"string"},{"name":"version","in":"path","description":"microservice version,if the version is empty, please enter \"null\"","required":true,"type":"string"},{"name":"status","in":"path","description":"status,1:abled  0:disabled","required":true,"type":"string"}],"responses":{"201":{"description":"successful operation","schema":{"$ref":"#/definitions/MicroServiceFullInfo"}},"500":{"description":"update status fail","schema":{"type":"string"}},"415":{"description":"Unprocessable MicroServiceInfo Entity ","schema":{"type":"string"}},"404":{"description":"microservice not found","schema":{"type":"string"}}}}}},"definitions":{"JVMMetrics":{"type":"object","properties":{"value":{"type":"number","format":"double"}}},"DiscoverInfo":{"type":"object","properties":{"ip":{"type":"string"},"port":{"type":"integer","format":"int32"},"enabled":{"type":"boolean","default":false}}},"IuiRouteInfo":{"type":"object","required":["servers","serviceName","url"],"properties":{"serviceName":{"type":"string"},"url":{"type":"string","example":"/test","description":"Target Service URL,start with /"},"control":{"type":"string","example":"0","description":"[control Range] 0:default   1:readonly  2:hidden ","enum":["0","1","2"]},"status":{"type":"string","example":"1","description":"[status] 1:abled    0:disabled ","enum":["0","1"]},"visualRange":{"type":"string","example":"1","description":"[visual Range]interSystem:0,inSystem:1","enum":["0","1"]},"useOwnUpstream":{"type":"string","example":"0","description":"[LB Policy]non_ip_hash:0,ip_hash:1","enum":["0","1"]},"servers":{"type":"array","items":{"$ref":"#/definitions/RouteServer"}}}},"Node":{"type":"object","required":["ip","port"],"properties":{"ip":{"type":"string"},"port":{"type":"string"},"ttl":{"type":"integer","format":"int32"}}},"RouteServer":{"type":"object","required":["ip","port"],"properties":{"ip":{"type":"string"},"port":{"type":"string"},"weight":{"type":"integer","format":"int32"}}},"MicroServiceInfo":{"type":"object","required":["protocol","serviceName","url"],"properties":{"serviceName":{"type":"string"},"version":{"type":"string","example":"v1"},"url":{"type":"string","example":"/api/serviceName/v1","description":"Target Service URL,start with /"},"protocol":{"type":"string","example":"REST","description":"Service Protocol","enum":["REST","UI","MQ","FTP","SNMP","TCP","UDP"]},"visualRange":{"type":"string","example":"1","description":"[visual Range]interSystem:0,inSystem:1","enum":["0","1"]},"lb_policy":{"type":"string","example":"hash","description":"lb policy","enum":["round-robin","hash","least_conn"]},"namespace":{"type":"string"},"nodes":{"type":"array","uniqueItems":true,"items":{"$ref":"#/definitions/Node"}}}},"HttpMetrics":{"type":"object","properties":{"count":{"type":"integer","format":"int32"},"max":{"type":"number","format":"double"},"mean":{"type":"number","format":"double"},"min":{"type":"number","format":"double"},"p50":{"type":"number","format":"double"},"p75":{"type":"number","format":"double"},"p95":{"type":"number","format":"double"},"p98":{"type":"number","format":"double"},"p99":{"type":"number","format":"double"},"p999":{"type":"number","format":"double"},"stddev":{"type":"number","format":"double"},"m15_rate":{"type":"number","format":"double"},"m1_rate":{"type":"number","format":"double"},"m5_rate":{"type":"number","format":"double"},"mean_rate":{"type":"number","format":"double"},"duration_units":{"type":"string"},"rate_units":{"type":"string"}}},"ApiRouteInfo":{"type":"object","required":["servers","serviceName","url","version"],"properties":{"serviceName":{"type":"string"},"version":{"type":"string","example":"v1"},"url":{"type":"string","example":"/test","description":"Target Service URL,start with /"},"apiJson":{"type":"string"},"apiJsonType":{"type":"string","example":"1","description":"[apiJson Type] 0:local file  1: remote file","enum":["0","1"]},"metricsUrl":{"type":"string"},"control":{"type":"string","example":"0","description":"[control Range] 0:default   1:readonly  2:hidden ","enum":["0","1","2"]},"status":{"type":"string","example":"1","description":"[status] 1:abled    0:disabled ","enum":["0","1"]},"visualRange":{"type":"string","example":"1","description":"[visual Range]interSystem:0,inSystem:1","enum":["0","1"]},"useOwnUpstream":{"type":"string","example":"0","description":"[LB Policy]non_ip_hash:0,ip_hash:1","enum":["0","1"]},"servers":{"type":"array","items":{"$ref":"#/definitions/RouteServer"}}}},"Gauges":{"type":"object","properties":{"jvm.attribute.uptime":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.Eden-Space.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.PS-Eden-Space.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.Perm-Gen.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.PS-Perm-Gen.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.Survivor-Space.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.PS-Survivor-Space.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.Tenured-Gen.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.PS-Old-Gen.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.pools.Code-Cache.usage":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.heap.init":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.non-heap.init":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.heap.used":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.non-heap.used":{"$ref":"#/definitions/JVMMetrics"},"jvm.memory.heap.max":{"$ref":"#/definitions/JVMMetrics"},"jvm.threads.runnable.count":{"$ref":"#/definitions/JVMMetrics"},"jvm.threads.timed_waiting.count":{"$ref":"#/definitions/JVMMetrics"},"jvm.threads.waiting.count":{"$ref":"#/definitions/JVMMetrics"},"jvm.threads.blocked.count":{"$ref":"#/definitions/JVMMetrics"},"jvm.threads.count":{"$ref":"#/definitions/JVMMetrics"}}},"MetricsInfo":{"type":"object","properties":{"gauges":{"$ref":"#/definitions/Gauges"},"timers":{"$ref":"#/definitions/Timers"}}},"ServiceAccessInfo":{"type":"object","properties":{"serviceType":{"type":"string"},"serviceName":{"type":"string"},"version":{"type":"string"},"accessAddr":{"type":"string"}}},"MicroServiceFullInfo":{"type":"object","required":["protocol","serviceName","url"],"properties":{"serviceName":{"type":"string"},"version":{"type":"string","example":"v1"},"url":{"type":"string","example":"/api/serviceName/v1","description":"Target Service URL,start with /"},"protocol":{"type":"string","example":"REST","description":"Service Protocol","enum":["REST","UI","MQ","FTP","SNMP","TCP","UDP"]},"visualRange":{"type":"string","example":"1","description":"[visual Range]interSystem:0,inSystem:1","enum":["0","1"]},"lb_policy":{"type":"string","example":"hash","description":"lb policy","enum":["round-robin","hash","least_conn"]},"namespace":{"type":"string"},"nodes":{"type":"array","uniqueItems":true,"items":{"$ref":"#/definitions/NodeInfo"}},"status":{"type":"string"}}},"NodeInfo":{"type":"object","required":["ip","port"],"properties":{"ip":{"type":"string"},"port":{"type":"string"},"ttl":{"type":"integer","format":"int32"},"nodeId":{"type":"string"},"expiration":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"CustomRouteInfo":{"type":"object","required":["servers","serviceName","url"],"properties":{"serviceName":{"type":"string"},"url":{"type":"string","example":"/test","description":"Target Service URL,start with /"},"control":{"type":"string","example":"0","description":"[control Range] 0:default   1:readonly  2:hidden ","enum":["0","1","2"]},"status":{"type":"string","example":"1","description":"[status] 1:abled    0:disabled ","enum":["0","1"]},"visualRange":{"type":"string","example":"1","description":"[visual Range]interSystem:0,inSystem:1","enum":["0","1"]},"useOwnUpstream":{"type":"string","example":"0","description":"[LB Policy]non_ip_hash:0,ip_hash:1","enum":["0","1"]},"servers":{"type":"array","items":{"$ref":"#/definitions/RouteServer"}}}},"Timers":{"type":"object","properties":{"org.openo.msb.resources.ApiRouteResource.addApiRoute":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.ApiRouteResource.deleteApiRoute":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.ApiRouteResource.getApiDocs":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.ApiRouteResource.getApiRoute":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.ApiRouteResource.getApiRoutes":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.ApiRouteResource.getServerIP":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.ApiRouteResource.updateApiRoute":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.IuiRouteResource.addIuiRoute":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.IuiRouteResource.deleteIuiRoute":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.IuiRouteResource.getIuiRoute":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.IuiRouteResource.getIuiRoutes":{"$ref":"#/definitions/HttpMetrics"},"org.openo.msb.resources.IuiRouteResource.updateIuiRoute":{"$ref":"#/definitions/HttpMetrics"},"io.dropwizard.jetty.MutableServletContextHandler.get-requests":{"$ref":"#/definitions/HttpMetrics"},"io.dropwizard.jetty.MutableServletContextHandler.post-requests":{"$ref":"#/definitions/HttpMetrics"},"io.dropwizard.jetty.MutableServletContextHandler.put-requests":{"$ref":"#/definitions/HttpMetrics"},"io.dropwizard.jetty.MutableServletContextHandler.delete-requests":{"$ref":"#/definitions/HttpMetrics"},"io.dropwizard.jetty.MutableServletContextHandler.other-requests":{"$ref":"#/definitions/HttpMetrics"}}}}};\r
-\r
-        const workflows = {\r
-            "1": {\r
-                planName: "plan1",\r
-                plan: {\r
-                    id: 'workflow1',\r
-                    name: 'workflow1',\r
-                    nodes: [],\r
-                    configs: {\r
-                        restConfigs: [{\r
-                            definition: "/s/swagger",\r
-                            name: "test",\r
-                            swaggerJson: JSON.stringify(swagger),\r
-                            version: "v2"\r
-                        }]\r
-                    }\r
-                },\r
-            },\r
-            "2": {\r
-                planName: "plan2",\r
-                plan: {\r
-                    id: 'workflow2',\r
-                    name: 'workflow2',\r
-                    nodes: [],\r
-                    configs: {\r
-                        restConfigs: []\r
-                    }\r
-                },\r
-            },\r
-            "3": {\r
-                planName: "plan3",\r
-                plan: workflowFJH,\r
-            } ,\r
-        };\r
-\r
-        const mockarray = [];\r
-        const mockobject = {};\r
-\r
-        const setting = {\r
-            "BackendType":"SDC",\r
-        };\r
-\r
-        const tenant = {tenant: "tenant1"};\r
-\r
-        return { workflows, swagger, mockarray,mockobject, setting, tenant};\r
-    }\r
-}\r
diff --git a/sdc-workflow-designer-ui/src/app/services/data/mockdata.ts b/sdc-workflow-designer-ui/src/app/services/data/mockdata.ts
deleted file mode 100644 (file)
index ad89e47..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-\r
-export const swaggerFjh = {"info":{"version":"1.0.0","contact":{"url":"https://gerrit.onap.org/r/#/admin/projects/vfc/nfvo/lcm","name":"ONAP VFC team","email":"onap-discuss@lists.onap.org"},"description":"VFC Network Service Lifecycle Management Rest API.","title":"ONAP VFC Network Service Lifecycle Management API"},"paths":{"/ns/sfcs/{sfcInstId}":{"delete":{"responses":{"204":{"description":"successful operation","schema":{"$ref":"#/definitions/DeleteResponse"}},"404":{"description":"the sfc instance id is wrong"},"500":{"description":"the url is invalid"}},"description":"","parameters":[{"required":true,"type":"string","description":"","in":"path","name":"sfcInstId"}],"produces":["application/json"],"tags":["sfc"],"summary":"delete sfc","consumes":["application/json"],"operationId":"delete_sfc"},"get":{"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/SfcInfo"}},"404":{"description":"the sfc instance id is wrong"},"500":{"description":"the url is invalid"}},"description":"","parameters":[{"description":"sfc instance id","required":true,"type":"string","name":"sfcInstId","in":"path"}],"produces":["application/json"],"tags":["sfc"],"summary":"query the specified sfc info","consumes":["application/json"],"operationId":"query_sfc"}},"/ns/{nsInstanceId}/postdeal":{"post":{"responses":{"202":{"description":""}},"description":"","parameters":[{"required":true,"type":"string","description":"","in":"path","name":"nsInstanceId"},{"schema":{"$ref":"#/definitions/NSInstPostDetailRequest"},"description":"request param","required":true,"name":"body","in":"body"}],"produces":["application/json"],"tags":["postdeal"],"summary":"ns postdeal","consumes":["application/json"],"operationId":"ns_postdeal"}},"/ns/vnfs":{"post":{"responses":{"201":{"description":"","schema":{"$ref":"#/definitions/VnfPostResponse"}}},"description":"","parameters":[{"schema":{"$ref":"#/definitions/VnfPostRequest"},"description":"instantiate request param","required":true,"name":"body","in":"body"}],"produces":["application/json"],"tags":["vnf"],"summary":"vnf create","consumes":["application/json"],"operationId":"create_vnf"}},"/ns/{ns_instance_id}/heal":{"post":{"responses":{"202":{"description":"","schema":{"$ref":"#/definitions/JobInfo"}},"500":{"description":"the url is invalid"}},"parameters":[{"required":true,"type":"string","description":"Identifier of the NS instance.","in":"path","name":"ns_instance_id"},{"schema":{"$ref":"#/definitions/NsHealRequest"},"description":"healVnfData","required":true,"name":"healVnfData","in":"body"}],"tags":["ns"],"description":"ns heal","summary":"ns heal","operationId":"ns_heal"}},"/jobs/{jobId}":{"post":{"responses":{"202":{"description":""}},"parameters":[{"required":true,"type":"string","description":"","in":"path","name":"jobId"},{"schema":{"$ref":"#/definitions/JobProgressRequest"},"description":"request param","required":true,"name":"body","in":"body"}],"tags":["job"],"description":"","summary":"jobstatus","operationId":"post_jobprogress"},"get":{"responses":{"202":{"description":"","schema":{"$ref":"#/definitions/JobDetailInfo"}}},"parameters":[{"required":true,"type":"string","description":"job Id","in":"path","name":"jobId"},{"required":true,"type":"string","description":"job response message id","in":"query","name":"responseId"}],"tags":["job"],"description":"","summary":"jobstatus","operationId":"get_jobstatus"}},"/ns/vls/{vlId}":{"delete":{"responses":{"204":{"description":"successful operation","schema":{"$ref":"#/definitions/DeleteVlResponse"}},"404":{"description":"the vl instance id is wrong"},"500":{"description":"the url is invalid"}},"description":"","parameters":[{"required":true,"type":"string","description":"","in":"path","name":"vlId"}],"produces":["application/json"],"tags":["vl"],"summary":"delete vl","consumes":["application/json"],"operationId":"delete_vl"},"get":{"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/VlInfo"}},"404":{"description":"the vl instance id is wrong"},"500":{"description":"the url is invalid"}},"description":"","parameters":[{"description":"vl instance id","required":true,"type":"string","name":"vlId","in":"path"}],"produces":["application/json"],"tags":["vl"],"summary":"query the specified vl info","consumes":["application/json"],"operationId":"query_vl"}},"/ns/vls":{"post":{"responses":{"201":{"description":"","schema":{"$ref":"#/definitions/VlPostResponse"}}},"description":"","parameters":[{"schema":{"$ref":"#/definitions/VlPostRequest"},"description":"instantiate request param","required":true,"name":"body","in":"body"}],"produces":["application/json"],"tags":["vl"],"summary":"vl create","consumes":["application/json"],"operationId":"create_vl"}},"/ns/sfcs":{"post":{"responses":{"201":{"description":"","schema":{"$ref":"#/definitions/SfcPostResponse"}}},"description":"","parameters":[{"schema":{"$ref":"#/definitions/SfcPostRequest"},"description":"request param","required":true,"name":"body","in":"body"}],"produces":["application/json"],"tags":["sfc"],"summary":"sfc create","consumes":["application/json"],"operationId":"create_sfc"}},"/ns/{ns_instance_id}":{"delete":{"responses":{"204":{"description":"The NS instance resource and the associated NS identifier were deleted successfully."}},"parameters":[{"required":true,"type":"string","description":"Identifier of the NS instance.","in":"path","name":"ns_instance_id"}],"tags":["ns"],"description":"ns delete","summary":"ns delete","operationId":"ns_delete"},"get":{"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/NsInstanceInfo"}}},"parameters":[],"tags":["ns"],"description":"ns get","summary":"ns get","operationId":"ns_instance_get"}},"/ns/vnfs/{vnfInstId}":{"delete":{"responses":{"204":{"description":"successful operation","schema":{"$ref":"#/definitions/DeleteResponse"}},"404":{"description":"the vl instance id is wrong"},"500":{"description":"the url is invalid"}},"description":"","parameters":[{"required":true,"type":"string","description":"","in":"path","name":"vnfInstId"}],"produces":["application/json"],"tags":["vnf"],"summary":"delete vnf","consumes":["application/json"],"operationId":"delete_vnf"},"get":{"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/VnfInfo"}},"404":{"description":"the vnf instance id is wrong"},"500":{"description":"the url is invalid"}},"description":"","parameters":[{"description":"vnf instance id","required":true,"type":"string","name":"vnfInstId","in":"path"}],"produces":["application/json"],"tags":["vnf"],"summary":"query the specified vnf info","consumes":["application/json"],"operationId":"query_vnf"}},"/ns":{"post":{"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/NsCreateResponse"}}},"parameters":[{"schema":{"$ref":"#/definitions/NsCreateRequest"},"description":"NS Instance Create Request","required":true,"name":"NSCreateRequest","in":"body"}],"tags":["ns"],"description":"ns create","summary":"ns create","operationId":"ns_create"},"get":{"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/NsInstancesInfo"}}},"parameters":[{"required":true,"type":"string","description":"job response message id","in":"query","name":"csarId"}],"tags":["ns"],"description":"ns get","summary":"ns get","operationId":"ns_instantces_get"}},"/ns/{ns_instance_id}/terminate":{"post":{"responses":{"202":{"description":"","schema":{"$ref":"#/definitions/JobInfo"}},"500":{"description":"the url is invalid"}},"parameters":[{"required":true,"type":"string","description":"Identifier of the NS instance.","in":"path","name":"ns_instance_id"},{"schema":{"$ref":"#/definitions/NsTerminateRequest"},"description":"NsTerminateRequest","required":true,"name":"NsTerminateRequest","in":"body"}],"tags":["ns"],"description":"ns terminate","summary":"ns terminate","operationId":"ns_terminate"}},"/ns/{nsInstanceId}/scale":{"post":{"responses":{"200":{"description":"","schema":{"$ref":"#/definitions/JobInfo"}},"201":{"description":"Invalid Request"}},"parameters":[{"required":true,"type":"string","description":"","in":"path","name":"nsInstanceId"},{"schema":{"$ref":"#/definitions/NsScaleRequest"},"description":"Scale NS Request Body","required":true,"name":"ScaleNSRequest","in":"body"}],"tags":["ns"],"description":"ns scale","summary":"ns scale","operationId":"ns_scale"}},"/mandb/{modelName}":{"delete":{"responses":{"204":{"description":"The tables were deleted successfully."}},"description":"ns table delete","parameters":[{"required":true,"type":"string","description":"model Name.","in":"path","name":"modelName"}],"produces":["application/json"],"tags":["db"],"summary":"ns table delete","consumes":["application/json"],"operationId":"ns_table_delete"},"get":{"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/TableInfo"}},"500":{"description":"the url is invalid"}},"description":"query ns table info","parameters":[{"required":true,"type":"string","description":"model Name.","in":"path","name":"modelName"}],"produces":["application/json"],"tags":["db"],"summary":"query ns table info","consumes":["application/json"],"operationId":"query_ns_table"}},"/ns/{nsInstanceId}/Instantiate":{"post":{"responses":{"200":{"description":"","schema":{"$ref":"#/definitions/JobInfo"}},"201":{"description":"Invalid Request"}},"parameters":[{"required":true,"type":"string","description":"","in":"path","name":"nsInstanceId"},{"schema":{"$ref":"#/definitions/NsInstantiateRequest"},"description":"NS Instantiate Request Body","required":true,"name":"NSInstantiateRequest","in":"body"}],"tags":["ns"],"description":"ns Instantiate","summary":"ns Instantiate","operationId":"ns_Instantiate"}}},"schemes":["http","https"],"produces":["application/json"],"basePath":"/api/nslcm/v1","definitions":{"NsInstanceInfo":{"type":"object","properties":{"nsState":{"type":"string"},"vnfInfo":{"items":{"$ref":"#/definitions/vnfInfo"},"type":"array"},"nsInstanceId":{"type":"string"},"nsdId":{"type":"string"},"vlInfo":{"items":{"$ref":"#/definitions/vlInfo"},"type":"array"},"nsName":{"type":"string"},"vnffgInfo":{"items":{"$ref":"#/definitions/vnffgInfo"},"type":"array"},"description":{"type":"string"}}},"JobDetailInfo":{"type":"object","properties":{"responseDescriptor":{"type":"object","properties":{"status":{"type":"string"},"responseHistoryList":{"items":{"$ref":"#/definitions/jobResponseInfo"},"type":"array"},"responseId":{"type":"string"},"errorCode":{"type":"string"},"progress":{"type":"string"},"statusDescription":{"type":"string"}}},"jobId":{"type":"string"}}},"VnfInfo":{"type":"object","properties":{"vnfInstId":{"type":"string"},"vnfName":{"type":"string"},"vnfStatus":{"type":"string"}}},"DeleteResponse":{"type":"object","properties":{"result":{"enum":[0,1],"type":"integer"},"detail":{"type":"string"}}},"NsHealRequest":{"type":"object","properties":{"vnfInstanceId":{"type":"string"},"cause":{"type":"string"},"additionalParams":{"type":"object","properties":{"action":{"type":"string"},"actionvminfo":{"type":"object","properties":{"vmname":{"type":"string"},"vmid":{"type":"string"}}}}}}},"NsScaleRequest":{"type":"object","properties":{"scaleNsByStepsData":{"$ref":"#/definitions/NsScaleByStepsData"},"scaleType":{"type":"string"}}},"jobResponseInfo":{"type":"object","properties":{"status":{"type":"string"},"progress":{"type":"string"},"responseId":{"type":"string"},"statusDescription":{"type":"string"},"errorCode":{"type":"string"}}},"NSInstPostDetailRequest":{"type":"object","properties":{"status":{"type":"string"}}},"VlInfo":{"type":"object","properties":{"vlId":{"type":"string"},"vlStatus":{"type":"string"},"vlName":{"type":"string"}}},"VnfPostResponse":{"type":"object","properties":{"vnfInstId":{"type":"string"},"jobId":{"type":"string"}}},"NsCreateRequest":{"type":"object","properties":{"nsName":{"type":"string"},"csarId":{"type":"string","description":"the NS package ID"},"description":{"type":"string"}}},"VlPostResponse":{"type":"object","properties":{"vlId":{"type":"string"},"result":{"enum":[0,1],"type":"integer"},"detail":{"type":"string"}}},"SfcPostRequest":{"type":"object","properties":{"sdnControllerId":{"type":"string"},"vnfInstanceData":{"items":{"type":"object"},"type":"array"},"additionalParamForVnf":{"items":{"type":"object"},"type":"array"},"nsInstanceId":{"type":"string"},"jobId":{"type":"string"},"additionalParamForNs":{"items":{"type":"object"},"type":"array"},"context":{"type":"string"},"sapData":{"items":{"type":"object"},"type":"array"},"fpindex":{"type":"string"}}},"NsTerminateRequest":{"type":"object","properties":{"gracefulTerminationTimeout":{"type":"string"},"terminationType":{"type":"string"}}},"JobProgressRequest":{"type":"object","properties":{"progress":{"type":"string"},"errcode":{"type":"string"},"desc":{"type":"string"}}},"SfcInfo":{"type":"object","properties":{"sfcName":{"type":"string"},"sfcInstId":{"type":"string"},"sfcStatus":{"type":"string"}}},"vnfInfo":{"type":"object","properties":{"vnfInstanceId":{"type":"string"},"vnfdId":{"type":"string"},"vnfInstanceName":{"type":"string"}}},"LocationConstraint":{"type":"object","properties":{"locationConstraints":{"type":"object","properties":{"vimid":{"type":"string"}}},"vnfProfileId":{"type":"string"}}},"NsCreateResponse":{"type":"object","properties":{"nsInstanceId":{"type":"string"}}},"VlPostRequest":{"type":"object","properties":{"vnfInstanceData":{"items":{"type":"object"},"type":"array"},"additionalParamForVnf":{"items":{"type":"object"},"type":"array"},"nsInstanceId":{"type":"string"},"flavourId":{"type":"string"},"pnfInfo":{"items":{"type":"object"},"type":"array"},"extNSVirtualLink":{"items":{"type":"object"},"type":"array"},"additionalParamForNs":{"items":{"type":"object"},"type":"array"},"context":{"type":"string"},"sapData":{"items":{"type":"object"},"type":"array"},"nestedNsInstanceId":{"items":{"type":"object"},"type":"array"},"jobId":{"type":"string"},"locationConstraints":{"items":{"type":"object"},"type":"array"},"vlIndex":{"type":"string"}}},"VnfPostRequest":{"type":"object","properties":{"vnfInstanceData":{"items":{"type":"object"},"type":"array"},"vnfIndex":{"type":"string"},"additionalParamForVnf":{"items":{"type":"object"},"type":"array"},"nsInstanceId":{"type":"string"},"flavourId":{"type":"string"},"pnfInfo":{"items":{"type":"object"},"type":"array"},"extNSVirtualLink":{"items":{"type":"object"},"type":"array"},"additionalParamForNs":{"items":{"type":"object"},"type":"array"},"context":{"type":"string"},"sapData":{"items":{"type":"object"},"type":"array"},"nestedNsInstanceId":{"items":{"type":"object"},"type":"array"},"jobId":{"type":"string"},"locationConstraints":{"items":{"type":"object"},"type":"array"}}},"DeleteVlResponse":{"type":"object","properties":{"result":{"enum":[0,1],"type":"integer"},"detail":{"type":"string"}}},"vlInfo":{"type":"object","properties":{"vldId":{"type":"string"},"vlInstanceName":{"type":"string"},"vlInstanceId":{"type":"string"},"relatedCpInstanceId":{"items":{"$ref":"#/definitions/cpInfo"},"type":"array"}}},"cpInfo":{"type":"object","properties":{"cpInstanceId":{"type":"string"},"cpdId":{"type":"string"},"cpInstanceName":{"type":"string"}}},"SfcPostResponse":{"type":"object","properties":{"sfcInstId":{"type":"string"},"jobId":{"type":"string"}}},"NsInstantiateRequest":{"type":"object","properties":{"additionalParamForNs":{"type":"string"},"LocationConstraints":{"items":{"$ref":"#/definitions/LocationConstraint"},"type":"array"}}},"JobInfo":{"type":"object","properties":{"jobId":{"type":"string"}}},"NsInstancesInfo":{"items":{"$ref":"#/definitions/NsInstanceInfo"},"type":"array"},"NsScaleByStepsData":{"type":"object","properties":{"numberOfSteps":{"type":"integer"},"scalingDirection":{"type":"string"},"aspectId":{"type":"string"}}},"vnffgInfo":{"type":"object","properties":{"cpId":{"type":"string"},"virtualLinkId":{"type":"string"},"vnfId":{"type":"string"},"pnfId":{"type":"string"},"nfp":{"type":"string"},"vnffgInstanceId":{"type":"string"}}},"TableInfo":{"type":"object","properties":{"count":{"type":"string"}}}},"swagger":"2.0","consumes":["application/json"]};\r
-\r
-export const workflowFJH = {"id":"fjh","name":"fjh","nodes":[{"id":"node0","name":"startEvent","type":"startEvent","position":{"top":31,"left":31,"width":200,"height":100},"connection":[{"sourceRef":"node0","targetRef":"node23"}],"parameters":[{"name":"vlCount","value":"","valueSource":"String","type":"String"},{"name":"vnfCount","value":"","valueSource":"String","type":"String"},{"name":"sfcCount","value":"","valueSource":"String","type":"String"},{"name":"object_context","value":"","valueSource":"String","type":"String"},{"name":"nsInstanceId","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForNs","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForVnf","value":"","valueSource":"String","type":"String"},{"name":"jobId","value":"","valueSource":"String","type":"String"},{"name":"sdnControllerId","value":"","valueSource":"String","type":"String"},{"name":"templateid","value":"","valueSource":"String","type":"String"},{"name":"instanceid","value":"","valueSource":"String","type":"String"},{"name":"sdnolcmurl","value":"","valueSource":"String","type":"String"},{"name":"statusurl","value":"","valueSource":"String","type":"String"}]},{"id":"node1","name":"endEvent","type":"endEvent","position":{"top":668,"left":955,"width":200,"height":100},"connection":[]},{"id":"node2","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":120,"left":169,"width":200,"height":100},"connection":[{"sourceRef":"node2","targetRef":"node3","condition":"${ vl_index <= vlCount and vl_status='active' }","name":"未完成"},{"sourceRef":"node2","targetRef":"node4","condition":"!( vl_index <= vlCount and vl_status='active' )","name":"创建完成"}]},{"id":"node3","name":"createVL","type":"restTask","position":{"top":213,"left":142,"width":200,"height":100},"connection":[{"sourceRef":"node3","targetRef":"node11"}],"produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"body","valueSource":"String","type":"String","position":"body","schema":{"$ref":"#/definitions/VlPostRequest"}}],"responses":[{"description":"","schema":{"$ref":"#/definitions/VlPostResponse"}}],"restConfigId":"nslcm","path":"/ns/vls","method":"post"},{"id":"node4","name":"restTask","type":"restTask","position":{"top":115,"left":358,"width":200,"height":100},"connection":[{"sourceRef":"node4","targetRef":"node5"}],"produces":[],"consumes":[],"parameters":[],"responses":[],"restConfigId":"nslcm","path":"","method":""},{"id":"node5","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":212,"left":383,"width":200,"height":100},"connection":[{"sourceRef":"node5","targetRef":"node6","condition":"未完成"},{"sourceRef":"node5","targetRef":"node12","condition":"创建完成"}]},{"id":"node6","name":"createVNF","type":"restTask","position":{"top":306,"left":352,"width":200,"height":100},"connection":[{"sourceRef":"node6","targetRef":"node7"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node7","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":558,"left":443,"width":200,"height":100},"connection":[{"sourceRef":"node7","targetRef":"node8"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node8","name":"query_vnf nslcm","type":"restTask","position":{"top":639,"left":216,"width":200,"height":100},"connection":[{"sourceRef":"node8","targetRef":"node9"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node9","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":539,"left":264,"width":200,"height":100},"connection":[{"sourceRef":"node9","targetRef":"node7","condition":"未完成"},{"sourceRef":"node9","targetRef":"node10","condition":"已完成"}]},{"id":"node10","name":"scriptTask","type":"scriptTask","position":{"top":303,"left":239,"width":200,"height":100},"connection":[{"sourceRef":"node10","targetRef":"node5"}]},{"id":"node11","name":"scriptTask","type":"scriptTask","position":{"top":207,"left":34,"width":200,"height":100},"connection":[{"sourceRef":"node11","targetRef":"node2"}]},{"id":"node12","name":"restTask","type":"restTask","position":{"top":205,"left":732,"width":200,"height":100},"connection":[{"sourceRef":"node12","targetRef":"node13"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node13","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":287,"left":757,"width":200,"height":100},"connection":[{"sourceRef":"node13","targetRef":"node14","condition":"未结束"},{"sourceRef":"node13","targetRef":"node18","condition":"已结束"}]},{"id":"node14","name":"createSfc","type":"restTask","position":{"top":440,"left":726,"width":200,"height":100},"connection":[{"sourceRef":"node14","targetRef":"node15"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node15","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":551,"left":754,"width":200,"height":100},"connection":[{"sourceRef":"node15","targetRef":"node16"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node16","name":"restTask","type":"restTask","position":{"top":642,"left":589,"width":200,"height":100},"connection":[{"sourceRef":"node16","targetRef":"node17"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node17","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":551,"left":614,"width":200,"height":100},"connection":[{"sourceRef":"node17","targetRef":"node15","condition":"未结束"},{"sourceRef":"node17","targetRef":"node19","condition":"已结束"}]},{"id":"node18","name":"restTask","type":"restTask","position":{"top":282,"left":927,"width":200,"height":100},"connection":[{"sourceRef":"node18","targetRef":"node20"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node19","name":"scriptTask","type":"scriptTask","position":{"top":275,"left":588,"width":200,"height":100},"connection":[{"sourceRef":"node19","targetRef":"node13"}]},{"id":"node20","name":"Assign_all_status","type":"scriptTask","position":{"top":380,"left":928,"width":200,"height":100},"connection":[{"sourceRef":"node20","targetRef":"node21"}]},{"id":"node21","name":"post_do","type":"restTask","position":{"top":497,"left":929,"width":200,"height":100},"connection":[{"sourceRef":"node21","targetRef":"node22"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node22","name":"jobstatus","type":"restTask","position":{"top":586,"left":927,"width":200,"height":100},"connection":[{"sourceRef":"node22","targetRef":"node1"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node23","name":"scriptTask","type":"scriptTask","position":{"top":16,"left":143,"width":200,"height":100},"connection":[{"sourceRef":"node23","targetRef":"node2"}],"scriptFormate":"javascript","script":"execution.setVariable(\"vl_index\", 1);\nexecution.setVariable(\"vl_status\", \"active\");"}],"configs":{"restConfigs":[{"id": "nslcm", "name":"nslcm","version":"v1","swagger":swaggerFjh,"definition":""}]}};\r
diff --git a/sdc-workflow-designer-ui/src/app/services/data/sdc.service.ts b/sdc-workflow-designer-ui/src/app/services/data/sdc.service.ts
deleted file mode 100644 (file)
index 0e2f111..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- */\r
-\r
-import { Injectable } from '@angular/core';\r
-import { Observable } from "rxjs/Observable";\r
-import { WorkflowNode } from "../../model/workflow/workflow-node";\r
-import { HttpService } from "../../util/http.service";\r
-import { PlanModel } from "../../model/plan-model";\r
-import { BackendService } from './backend.service';\r
-import { NodeTemplate } from '../../model/topology/node-template';\r
-\r
-/**\r
- * SdcService\r
- * provides data access from sdc\r
- */\r
-@Injectable()\r
-export class SdcService extends BackendService {\r
-    private workflowId: string;\r
-\r
-    public getBackendType(): string {\r
-        return "SDC";\r
-    }\r
-    public setParameters(params: any) {\r
-        this.workflowId = params;\r
-        this.loadPlans().subscribe(plans => {\r
-            const map = new Map<string, any>();\r
-            for(let id of Object.keys(plans)) {\r
-                map.set(id, plans[id]);\r
-            }\r
-            this.broadcastService.broadcast(this.broadcastService.workflows, map);\r
-        });\r
-    }\r
-    public loadNodeTemplates(): Observable<NodeTemplate[]> {\r
-        // TODO load data from sdc\r
-        const url = 'api/mockarray';\r
-        return this.httpService.get(url).map(response => response.data);\r
-    }\r
-    public loadTopologyProperties(nodeTemplate: NodeTemplate): Observable<string[]> {\r
-        // TODO load data from sdc\r
-        const url = 'api/mockarray';\r
-        return this.httpService.get(url).map(response => response.data);\r
-    }\r
-    public loadNodeTemplateInterfaces(nodeTemplate: NodeTemplate): Observable<string[]> {\r
-        // TODO load data from sdc\r
-        const url = 'api/mockarray';\r
-        return this.httpService.get(url).map(response => response.data);\r
-    }\r
-    public loadNodeTemplateOperations(nodeTemplate: NodeTemplate, interfaceName: string): Observable<string[]> {\r
-        // TODO load data from sdc\r
-        const url = 'api/mockarray';\r
-        return this.httpService.get(url).map(response => response.data);\r
-    }\r
-    public loadNodeTemplateOperationParameter(nodeTemplate: NodeTemplate, interfaceName: string, operation: string): Observable<any> {\r
-        // TODO load data from sdc\r
-        const url = 'api/mockobject';\r
-        return this.httpService.get(url).map(response => response.data);\r
-    }\r
-\r
-    public loadPlans(): Observable<any> {\r
-        // TODO load data from sdc\r
-        const url = 'api/workflows';\r
-        return this.httpService.get(url).map(response => response.data);\r
-    }\r
-\r
-    public loadPlan(): Observable<PlanModel> {\r
-        // TODO load data from sdc\r
-        const url = `api/workflows/${this.workflowId}`;\r
-        return this.httpService.get(url).map(response => response.data as PlanModel);\r
-    }\r
-\r
-    public save(data: any): Observable<boolean> {\r
-        // TODO save workflow design to sdc\r
-        const url = `api/workflows/${data.name}`;\r
-        return this.httpService.put(url, JSON.stringify(data.planModel)).map(() => true);\r
-    }\r
-\r
-}\r
diff --git a/sdc-workflow-designer-ui/src/app/services/display-info.service.ts b/sdc-workflow-designer-ui/src/app/services/display-info.service.ts
new file mode 100644 (file)
index 0000000..a3a5768
--- /dev/null
@@ -0,0 +1,27 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+import { Injectable } from "@angular/core";\r
+import { HttpService } from "../util/http.service";\r
+import { Observable } from "rxjs";\r
+import { ModelService } from "./model.service";\r
+\r
+@Injectable()\r
+export class DisplayInfoService {\r
+    private displayInfoUrl = '/api/workflow-modeler/v1/ext-activities/displayInfo?scene=';\r
+\r
+    constructor(private modelService: ModelService, private httpService: HttpService) {\r
+    }\r
+\r
+    public getDisplayInfo(): Observable<any> {\r
+        return this.httpService.get(this.displayInfoUrl + this.modelService.getPlanModel().scene);\r
+    }\r
+}
\ No newline at end of file
diff --git a/sdc-workflow-designer-ui/src/app/services/interface.service.spec.ts b/sdc-workflow-designer-ui/src/app/services/interface.service.spec.ts
new file mode 100644 (file)
index 0000000..0aeb3f5
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { TestBed, inject } from '@angular/core/testing';
+
+import { InterfaceService } from './interface.service';
+
+describe('PersistenceService', () => {
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      providers: [InterfaceService]
+    });
+  });
+
+  it('should be created', inject([InterfaceService], (service: InterfaceService) => {
+    expect(service).toBeTruthy();
+  }));
+});
diff --git a/sdc-workflow-designer-ui/src/app/services/interface.service.ts b/sdc-workflow-designer-ui/src/app/services/interface.service.ts
new file mode 100644 (file)
index 0000000..c9ef87d
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { Injectable } from '@angular/core';
+import { ActivatedRoute } from '@angular/router/';
+
+import { Observable } from 'rxjs/Observable';
+import { TranslateService } from '@ngx-translate/core';
+
+import { HttpService } from '../util/http.service';
+import { BroadcastService } from './broadcast.service';
+import { NoticeService } from './notice.service';
+import { PlanModel } from '../model/plan-model';
+
+@Injectable()
+export class InterfaceService {
+  private static ModelUrl = '/api/workflow-modeler/v1/models/';
+  constructor(private activatedRoute: ActivatedRoute, private http: HttpService,
+    private broadcast: BroadcastService, private notice: NoticeService, private translate: TranslateService) {
+    this.getModelData();
+  }
+
+  public getModelData() {
+    this.activatedRoute.queryParams.subscribe(queryParams => {
+      let modelId = queryParams.id;
+      this.http.get(InterfaceService.ModelUrl + modelId).subscribe(data => {
+        this.broadcast.broadcast(this.broadcast.initModel, data);
+      }, error => {
+        this.translate.get('WORKFLOW.MSG.LOAD_FAIL').subscribe((res: string) => {
+          this.notice.error(res);
+        });
+      });
+    });
+  }
+
+  public saveModelData(planModel: PlanModel): Observable<PlanModel> {
+    return this.http.put(InterfaceService.ModelUrl + planModel.id, planModel);
+  }
+}
index e90efa7..0cf93ef 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 
-import { Injectable } from '@angular/core';
+import {Injectable} from '@angular/core';
 import * as jsp from 'jsplumb';
 
-import { Subscription } from 'rxjs/Subscription';
-import { WorkflowNode } from '../model/workflow/workflow-node';
-import { BroadcastService } from './broadcast.service';
-import { ModelService } from './model.service';
-import { SequenceFlow } from '../model/workflow/sequence-flow';
-import { Position } from '../model/workflow/position';
+import {Subscription} from 'rxjs/Subscription';
+import {WorkflowNode} from '../model/workflow/workflow-node';
+import {BroadcastService} from './broadcast.service';
+import {ModelService} from './model.service';
+import {SequenceFlow} from '../model/workflow/sequence-flow';
+import {Position} from '../model/workflow/position';
 
 /**
  * JsPlumbService
@@ -46,17 +46,6 @@ export class JsPlumbService {
                 }
             }
         });
-
-        this.broadcastService.planModel$.subscribe(Workflow => {
-            this.jsplumbInstanceMap.get(this.modelService.rootNodeId).reset();
-            this.unsubscriptionAll();
-            this.buttonDraggable();
-            this.buttonDroppable();
-        });
-    }
-
-    private unsubscriptionAll() {
-        this.subscriptionMap.forEach(subscription => subscription.unsubscribe());
     }
 
     public connectChildrenNodes(parentNodeId: string) {
@@ -121,7 +110,7 @@ export class JsPlumbService {
                     width: 11,
                     length: 12
                 }],
-                ['Label', { label: '', id: 'label' }]
+                ['Label', {label: '', id: 'label'}]
             ]
         });
 
@@ -206,7 +195,7 @@ export class JsPlumbService {
     public deleteConnect(sourceId: string, targetId: string) {
         const sourceNode = this.modelService.getNodeMap().get(sourceId);
         const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);
-        const connectionSelection = jsplumbInstance.select({ source: sourceId, target: targetId });
+        const connectionSelection = jsplumbInstance.select({source: sourceId, target: targetId});
         this.unsubscription4Connection(connectionSelection);
         connectionSelection.delete();
     }
@@ -214,7 +203,7 @@ export class JsPlumbService {
     public setLabel(sourceId: string, targetId: string, label: string) {
         const sourceNode = this.modelService.getNodeMap().get(sourceId);
         const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);
-        const connections = jsplumbInstance.select({ source: sourceId, target: targetId });
+        const connections = jsplumbInstance.select({source: sourceId, target: targetId});
         connections.setLabel(label);
     }
 
@@ -279,7 +268,7 @@ export class JsPlumbService {
                 if (sourceId === targetId) {
                     return false;
                 }
-                const sameConnections = this.instance.getConnections({ source: sourceId, target: targetId });
+                const sameConnections = this.instance.getConnections({source: sourceId, target: targetId});
                 if (sameConnections && 0 < sameConnections.length) {
                     return false;
                 }
@@ -332,6 +321,8 @@ export class JsPlumbService {
     private drop(event) {
         const dragEl = event.drag.el;
         const dropEl = event.drop.el;
+        console.log(this.modelService.getNodes());
+
 
         this.resizeParent(dragEl, dropEl);
 
@@ -345,7 +336,8 @@ export class JsPlumbService {
         dragEl.style.left = left + 'px';
 
         // 12 is title height
-        this.modelService.updatePosition(dragEl.id, left, top, dragEl.getBoundingClientRect().width, dragEl.getBoundingClientRect().height - 12);
+        const nameHeight = this.getNodeNameHeight(dragEl);
+        this.modelService.updatePosition(dragEl.id, left, top, dragEl.getBoundingClientRect().width, dragEl.getBoundingClientRect().height - nameHeight);
 
         const originalParentNode = this.getParentNodeEl(dragEl);
         const originalParentNodeId = originalParentNode ? originalParentNode.id : this.modelService.rootNodeId;
@@ -354,6 +346,17 @@ export class JsPlumbService {
         this.changeParent(dragEl.id, originalParentNodeId, targetParentNodeId);
     }
 
+    private getNodeNameHeight(element: any): number {
+        const children = element.children;
+        if (children && children.length) {
+            const nameElement = children[0];
+            if (nameElement && nameElement.className === 'name') {
+                return nameElement.getBoundingClientRect().height;
+            }
+        }
+        return 0;
+    }
+
     private changeParent(id: string, originalParentNodeId: string, targetParentNodeId: string) {
         if (originalParentNodeId !== targetParentNodeId) {
             this.jsplumbInstanceMap.get(originalParentNodeId).removeAllEndpoints(id);
@@ -402,6 +405,10 @@ export class JsPlumbService {
             drop: event => {
                 const el = jsplumbInstance.getSelector(event.drag.el);
                 const type = el.attributes.nodeType.value;
+                let typeId = null;
+                if (el.attributes.nodeTypeId && el.attributes.nodeTypeId.value) {
+                    typeId = el.attributes.nodeTypeId.value;
+                }
                 // Mouse position minus drop canvas start position plus scroll position.
                 let left = event.e.x - event.drop.pagePosition[0] + event.drop.el.scrollLeft;
                 let top = event.e.y - event.drop.pagePosition[1] + event.drop.el.scrollTop;
@@ -411,8 +418,8 @@ export class JsPlumbService {
                 if (0 > top) {
                     top = 0;
                 }
-                const name = event.drag.el.children[1].innerText;
-                this.modelService.addNode(name, type, left, top);
+                const name = el.attributes.name.value;
+                this.modelService.addNode(type, typeId, name, left, top);
             },
         });
     }
@@ -421,9 +428,9 @@ export class JsPlumbService {
         const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);
 
         // unsubscription4Connection
-        const connectionsAsSource = jsplumbInstance.select({ source: node.id });
+        const connectionsAsSource = jsplumbInstance.select({source: node.id});
         this.unsubscription4Connection(connectionsAsSource);
-        const connectionsAsTarget = jsplumbInstance.select({ target: node.id });
+        const connectionsAsTarget = jsplumbInstance.select({target: node.id});
         this.unsubscription4Connection(connectionsAsTarget);
 
         jsplumbInstance.remove(node.id);
@@ -447,11 +454,12 @@ export class JsPlumbService {
         if (leftResized || rightResized || topResized || bottomResized) {
             if (parentElement.classList.contains('node')) {
                 const rect = parentElement.getBoundingClientRect();
+                const nameHeight = this.getNodeNameHeight(parentElement);
                 this.modelService.updatePosition(parentElement.id,
                     parentElement.offsetLeft,
                     parentElement.offsetTop,
                     // title height
-                    rect.width, rect.height - 12);
+                    rect.width, rect.height - nameHeight);
             }
             this.resizeParent(parentElement, parentElement.parentNode);
         }
@@ -547,7 +555,7 @@ export class JsPlumbService {
         const len = parentElment.children.length;
         for (let i = 0; i < len; i++) {
             const childElment = parentElment.children[i];
-            if (childElment.localName === 'b4t-node') {
+            if (childElment.localName === 'wfm-node') {
                 this.translateElement(childElment.children[0], left, top, 0, 0);
             }
         }
index b0ce69f..8cb7b86 100644 (file)
@@ -15,7 +15,13 @@ import { isNullOrUndefined } from 'util';
 import { PlanModel } from '../model/plan-model';
 import { PlanTreeviewItem } from '../model/plan-treeview-item';
 import { RestConfig } from '../model/rest-config';
-import { Swagger, SwaggerModel, SwaggerModelSimple, SwaggerPrimitiveObject, SwaggerReferenceObject } from '../model/swagger';
+import {
+    Swagger,
+    SwaggerModel,
+    SwaggerModelSimple,
+    SwaggerPrimitiveObject,
+    SwaggerReferenceObject
+} from '../model/swagger';
 import { ErrorEvent } from '../model/workflow/error-event';
 import { IntermediateCatchEvent } from '../model/workflow/intermediate-catch-event';
 import { NodeType } from '../model/workflow/node-type.enum';
@@ -32,8 +38,13 @@ import { ValueSource } from '../model/value-source.enum';
 import { BroadcastService } from './broadcast.service';
 import { RestService } from './rest.service';
 import { SwaggerTreeConverterService } from './swagger-tree-converter.service';
-import { ScriptTask } from "../model/workflow/script-task";
 import { TimerEventDefinition, TimerEventDefinitionType } from "../model/workflow/timer-event-definition";
+import { InterfaceService } from './interface.service';
+import { ServiceTask } from '../model/workflow/service-task';
+import { NodeTypeService } from './node-type.service';
+import { WorkflowUtil } from '../util/workflow-util';
+import { TranslateService } from '@ngx-translate/core';
+import { NoticeService } from './notice.service';
 
 /**
  * ModelService
@@ -44,10 +55,13 @@ export class ModelService {
     public rootNodeId = 'root';
 
     private planModel: PlanModel = new PlanModel();
+    private tempPlanModel: PlanModel = new PlanModel();
 
-    constructor(private broadcastService: BroadcastService, private restService: RestService) {
-        this.broadcastService.planModel$.subscribe(plan => {
-            plan.nodes.forEach(node => {
+    constructor(private interfaceService: InterfaceService, private broadcastService: BroadcastService,
+        private restService: RestService, private nodeTypeService: NodeTypeService,
+        private translate: TranslateService, private notice: NoticeService) {
+        this.broadcastService.initModel$.subscribe(planModel => {
+            planModel.data.nodes.forEach(node => {
                 switch (node.type) {
                     case NodeType[NodeType.startEvent]:
                         node.position.width = 56;
@@ -93,16 +107,22 @@ export class ModelService {
                         break;
                 }
             });
-            this.planModel = plan;
-        });
-        this.broadcastService.updateModelRestConfig$.subscribe(restConfigs => {
-            this.updateRestConfig(restConfigs);
+            this.planModel = planModel;
+            this.tempPlanModel = WorkflowUtil.deepClone(this.planModel);
         });
+        // Do not use restConfig property.
+        // this.broadcastService.updateModelRestConfig$.subscribe(restConfigs => {
+        //     this.updateRestConfig(restConfigs);
+        // });
+    }
+
+    public getPlanModel(): PlanModel {
+        return this.planModel;
     }
 
     public getChildrenNodes(parentId: string): WorkflowNode[] {
         if (!parentId || parentId === this.rootNodeId) {
-            return this.planModel.nodes;
+            return this.planModel.data.nodes;
         } else {
             const node = this.getNodeMap().get(parentId);
             if (node.type === 'subProcess') {
@@ -114,7 +134,7 @@ export class ModelService {
     }
 
     public getNodes(): WorkflowNode[] {
-        return this.planModel.nodes;
+        return this.planModel.data.nodes;
     }
 
     public getSequenceFlow(sourceRef: string, targetRef: string): SequenceFlow {
@@ -127,11 +147,76 @@ export class ModelService {
         }
     }
 
-    public addNode(name: string, type: string, left: number, top: number) {
-        const id = this.createId();
+    public addNode(type: string, typeId: string, name: string, left: number, top: number) {
+        const id = this.generateNodeProperty('id', type);
+        const nodeName = this.generateNodeProperty('name', name);
         const workflowPos = new Position(left, top);
-        const node = this.createNodeByType(id, name, type, workflowPos);
-        this.planModel.nodes.push(node);
+        let node;
+        if ('serviceTask' === type || 'scriptTask' === type || 'restTask' === type) {
+            node = this.createNodeByTypeId(id, nodeName, type, typeId, workflowPos);
+        } else {
+            node = this.createNodeByType(id, nodeName, type, workflowPos);
+        }
+        this.planModel.data.nodes.push(node);
+    }
+
+    private generateNodeProperty(key: string, type: string): string {
+        let nodeProperty = type;
+        const nodes = this.getNodes();
+        console.log(nodes);
+        const existNode = nodes.find(node => node[key] === nodeProperty);
+        if (existNode) {
+            let count = 2;
+            do {
+                nodeProperty = type + '_' + count;
+                count++;
+            } while (nodes.find(node => node[key] === nodeProperty))
+        }
+        return nodeProperty;
+    }
+
+    private generateNodeName(typeId: string): string {
+        const language = this.translate.currentLang.indexOf('en') > -1 ? 'en_US' : 'zh_CN';
+        const nodeType = this.nodeTypeService.getNodeDataTypeById(typeId);
+        let displayName;
+        if (nodeType.displayName && nodeType.displayName[language]) {
+            displayName = nodeType.displayName[language];
+        } else {
+            displayName = nodeType.type;
+        }
+        return this.generateNodeProperty('name', displayName);
+    }
+
+    public createNodeByTypeId(id: string, name: string, type: string, typeId: string, position: Position): WorkflowNode {
+        const nodeDataType = this.nodeTypeService.getNodeDataTypeById(typeId);
+        const initPosition = new Position(position.left, position.top, nodeDataType.icon.width, nodeDataType.icon.height);
+        // switch (type) {
+        //     case NodeType[NodeType.serviceTask]:
+        //         let serviceTask: ServiceTask = {
+        //             id: id, type: type, name: name, parentId: this.rootNodeId,
+        //             position: initPosition, connection: [], class: nodeDataType.activity.class,
+        //             input: nodeDataType.activity.input, output: nodeDataType.activity.output
+        //         };
+        //         return serviceTask;
+        //     case NodeType[NodeType.scriptTask]:
+        //         let scriptTask: ScriptTask = {
+        //             id: id, type: type, name: name, parentId: this.rootNodeId,
+        //             position: initPosition, connection: [], scriptFormat: nodeDataType.activity.scriptFormat,
+        //             script: nodeDataType.activity.script
+        //         };
+        //         return scriptTask;
+        //     case NodeType[NodeType.restTask]:
+        //         let restTaskNode: RestTask = {
+        //             id: id, type: type, name: name, parentId: this.rootNodeId,
+        //             position: initPosition, connection: [], produces: [], consumes: [], parameters: [], responses: []
+        //         };
+        //         return restTaskNode;
+        //     default:
+        let node: WorkflowNode = {
+            id: id, type: type, typeId: nodeDataType.id, icon: nodeDataType.icon.name, name: name,
+            parentId: this.rootNodeId, position: initPosition, connection: []
+        };
+        return node;
     }
 
     private createNodeByType(id: string, name: string, type: string, position: Position): WorkflowNode {
@@ -150,17 +235,16 @@ export class ModelService {
                     position: bigPosition, connection: []
                 };
                 return endEventNode;
-            case NodeType[NodeType.restTask]:
-                let restTaskNode: RestTask = {
-                    id: id, type: type, name: name, parentId: this.rootNodeId,
-                    position: bigPosition, connection: [], produces: [], consumes: [], parameters: [], responses: []
-                };
-                return restTaskNode;
             case NodeType[NodeType.errorStartEvent]:
             case NodeType[NodeType.errorEndEvent]:
                 let errorEventNode: ErrorEvent = {
-                    id: id, type: type, name: '', parentId: this.rootNodeId,
-                    position: smallPosition, connection: [], parameter: new Parameter('errorRef', '', ValueSource[ValueSource.String])
+                    id: id,
+                    type: type,
+                    name: '',
+                    parentId: this.rootNodeId,
+                    position: smallPosition,
+                    connection: [],
+                    parameter: new Parameter('errorRef', '', ValueSource[ValueSource.string])
                 };
                 return errorEventNode;
             case NodeType[NodeType.toscaNodeManagementTask]:
@@ -177,16 +261,15 @@ export class ModelService {
                 return subProcess;
             case NodeType[NodeType.intermediateCatchEvent]:
                 let intermediateCatchEvent: IntermediateCatchEvent = {
-                    id: id, type: type, name: name, parentId: this.rootNodeId,
-                    position: bigPosition, connection: [], timerEventDefinition: <TimerEventDefinition>{ type: TimerEventDefinitionType[TimerEventDefinitionType.timeDuration] }
+                    id: id,
+                    type: type,
+                    name: name,
+                    parentId: this.rootNodeId,
+                    position: bigPosition,
+                    connection: [],
+                    timerEventDefinition: <TimerEventDefinition>{ type: TimerEventDefinitionType[TimerEventDefinitionType.timeDuration] }
                 };
                 return intermediateCatchEvent;
-            case NodeType[NodeType.scriptTask]:
-                let scriptTask: ScriptTask = {
-                    id: id, type: type, name: name, parentId: this.rootNodeId,
-                    position: bigPosition, connection: [], scriptFormat: 'JavaScript'
-                };
-                return scriptTask;
             case NodeType[NodeType.exclusiveGateway]:
             case NodeType[NodeType.parallelGateway]:
                 let getway: WorkflowNode = {
@@ -207,34 +290,6 @@ export class ModelService {
         return undefined !== object.type;
     }
 
-    // public createNodeByJson(obj: any): WorkflowNode {
-    // let node;
-    // switch (obj.type) {
-    //     case NodeType[NodeType.startEvent]:
-    //         node = new StartEvent(obj.name, obj.id, obj.type, this.rootNodeId, obj.position);
-    //         node.parameters = obj.parameters;
-    //         return node;
-    //     case NodeType[NodeType.restTask]:
-    //         node = new RestTask(obj.name, obj.id, obj.type, this.rootNodeId, obj.position);
-    //         node.
-    //     case NodeType[NodeType.errorStartEvent]:
-    //         return new ErrorEvent(type, id, type, this.rootNodeId, position);
-    //     case NodeType[NodeType.errorEndEvent]:
-    //         return new ErrorEvent(type, id, type, this.rootNodeId, position);
-    //     case NodeType[NodeType.toscaNodeManagementTask]:
-    //         return new ToscaNodeTask(type, id, type, this.rootNodeId, position);
-    //     case NodeType[NodeType.subProcess]:
-    //         return new SubProcess(type, id, type, this.rootNodeId, position);
-    //     case NodeType[NodeType.intermediateCatchEvent]:
-    //         return new IntermediateCatchEvent(type, id, type, this.rootNodeId, position);
-    //     case NodeType[NodeType.scriptTask]:
-    //         return new ScriptTask(type, id, type, this.rootNodeId, position);
-    //     default:
-    //         return new WorkflowNode(type, id, type, this.rootNodeId, position);
-    // }
-    // return node;
-    // }
-
     public changeParent(id: string, originalParentId: string, targetParentId: string) {
         if (originalParentId === targetParentId) {
             return;
@@ -246,7 +301,7 @@ export class ModelService {
         if (targetParentId) {
             this.addChild(targetParentId, node);
         } else {
-            this.planModel.nodes.push(node);
+            this.planModel.data.nodes.push(node);
         }
     }
 
@@ -259,13 +314,13 @@ export class ModelService {
     }
 
     public updateRestConfig(restConfigs: RestConfig[]): void {
-        this.planModel.configs = { restConfigs: restConfigs };
+        this.planModel.data.configs = { restConfigs: restConfigs };
         // console.log(this.planModel.configs);
     }
 
     public getNodeMap(): Map<string, WorkflowNode> {
         const map = new Map<string, WorkflowNode>();
-        this.toNodeMap(this.planModel.nodes, map);
+        this.toNodeMap(this.planModel.data.nodes, map);
         return map;
     }
 
@@ -423,7 +478,7 @@ export class ModelService {
         const item = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);
         item.children.push(this.createStatusCodeTreeViewItem(node.id));
 
-        if (node.responses.length !== 0) { // load rest responses
+        if (node.responses && node.responses.length !== 0) { // load rest responses
             const responseItem = this.createResponseTreeViewItem(node.id);
             item.children.push(responseItem);
             // todo: should list all available response or only the first one?
@@ -491,11 +546,28 @@ export class ModelService {
         return targetNode !== undefined;
     }
 
-    public save() {
+    public save(callback?: Function) {
         console.log('****************** save data *********************');
-        console.log(this.planModel);
-
-        this.broadcastService.broadcast(this.broadcastService.saveEvent, this.planModel);
+        console.log(JSON.stringify(this.planModel));
+        // Check data
+        if(!this.checkData()){
+            return;
+        }
+        this.interfaceService.saveModelData(this.planModel).subscribe(response => {
+            this.translate.get('WORKFLOW.MSG.SAVE_SUCCESS').subscribe((res: string) => {
+                this.notice.success(res);
+                // Update the cache.
+                this.tempPlanModel = WorkflowUtil.deepClone(this.planModel);
+                if (callback) {
+                    callback();
+                }
+            });
+        }, error => {
+            this.translate.get('WORKFLOW.MSG.SAVE_FAIL').subscribe((res: string) => {
+                this.notice.error(res);
+            });
+        });
+        ;
     }
 
     private createId() {
@@ -510,4 +582,44 @@ export class ModelService {
 
         return 'node' + nodeMap.size;
     }
+
+    public isModify(): boolean {
+        // Compare the cache.
+        return JSON.stringify(this.planModel) != JSON.stringify(this.tempPlanModel);
+    }
+
+    private checkData(): boolean {
+        if (this.planModel && this.planModel.data && this.planModel.data.nodes) {
+            let nodes = this.planModel.data.nodes;
+            for (let index = 0; index < nodes.length; index++) {
+                const node = nodes[index];
+                if (NodeType[NodeType.startEvent] === node.type) {
+                    let startEvent = node as StartEvent;
+                    if (startEvent.parameters) {
+                        for (let i = 0; i < startEvent.parameters.length; i++) {
+                            const parameter = startEvent.parameters[i];
+                            if (!parameter.name) {
+                                this.translate.get('WORKFLOW.MSG.PROCESS_VARIABLE_EMPTY').subscribe((res: string) => {
+                                    this.notice.error(res);
+                                });
+                                return false;
+                            }
+                            if(i + 1 < startEvent.parameters.length){
+                            for (let j = i + 1; j < startEvent.parameters.length; j++) {
+                                const param = startEvent.parameters[j];
+                                if(parameter.name === param.name){
+                                    this.translate.get('WORKFLOW.MSG.PROCESS_VARIABLE_SAME').subscribe((res: string) => {
+                                        this.notice.error(res);
+                                    });
+                                    return false;
+                                }
+                            }
+                        }
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
 }
diff --git a/sdc-workflow-designer-ui/src/app/services/node-type.service.ts b/sdc-workflow-designer-ui/src/app/services/node-type.service.ts
new file mode 100644 (file)
index 0000000..a40ad50
--- /dev/null
@@ -0,0 +1,68 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+import { Injectable } from "@angular/core";\r
+import { HttpService } from "../util/http.service";\r
+import { BroadcastService } from "./broadcast.service";\r
+import { NodeDataType } from "../model/node-data-type/node-data-type";\r
+import { Parameter } from "../model/workflow/parameter";\r
+import { TranslateService } from "@ngx-translate/core";\r
+\r
+@Injectable()\r
+export class NodeTypeService {\r
+    private nodeDataTypes: NodeDataType[] = [];\r
+    private nodeDataTypeUrl = '/api/workflow-modeler/v1/ext-activities?sence=test';\r
+\r
+    constructor(private httpService: HttpService, private translateService: TranslateService,\r
+        private broadcastService: BroadcastService) {\r
+        this.initNodeDataTypes();\r
+    }\r
+\r
+    private initNodeDataTypes(): void {\r
+        this.httpService.get(this.nodeDataTypeUrl)\r
+            .toPromise()\r
+            .then(resp => {\r
+                if (resp && 0 < resp.length) {\r
+                    this.nodeDataTypes = resp;\r
+                }\r
+                this.broadcastService.broadcast(this.broadcastService.updateNodeTypeConfig, null);\r
+            });\r
+    }\r
+\r
+    public getAllNodeDataTypes(): NodeDataType[] {\r
+        return this.nodeDataTypes;\r
+    }\r
+\r
+    public getNodeDataTypeById(id: string): NodeDataType | null {\r
+        return this.nodeDataTypes.find(nodeDataType => nodeDataType.id === id);\r
+    }\r
+\r
+    public GetI18nName(key: string, displayName: any): string {\r
+        //todo: add logic\r
+        let name = key;\r
+        if (displayName) {\r
+            let language = 'zh_CN';\r
+            if (this.translateService.currentLang.indexOf('en') > -1) {\r
+                language = 'en_US';\r
+            }\r
+            if (displayName.language && '' != displayName.language) {\r
+                name = displayName.language;\r
+            }\r
+        }\r
+        return name;\r
+    }\r
+\r
+    public static GetParameterByDataType(nodeDataType: any): Parameter {\r
+        //todo: add logic\r
+        let param = new Parameter('', '', '');\r
+        return param;\r
+    }\r
+}
\ No newline at end of file
index 1db5147..e3bde51 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- *******************************************************************************/\r
-\r
-import { Injectable } from '@angular/core';\r
-import { Http, RequestOptionsArgs } from '@angular/http';\r
-import { Observable } from 'rxjs/Rx';\r
-import { isNullOrUndefined } from 'util';\r
-\r
-import { SwaggerMethod } from '../model/swagger';\r
-import { SwaggerResponse } from '../model/swagger';\r
-import { Swagger, SwaggerSchemaObject } from '../model/swagger';\r
-import { RestConfig } from '../model/rest-config';\r
-import { HttpService } from '../util/http.service';\r
-import { BroadcastService } from './broadcast.service';\r
-import { NoticeService } from './notice.service';\r
-\r
-@Injectable()\r
-export class RestService {\r
-\r
-    private restConfigs: RestConfig[] = [];\r
-    // private runtimeURL = '/openoapi/catalog/v1/sys/config';\r
-    private runtimeURL = '/api/tenant';\r
-    // private msbPublishServiceURL = '/api/msdiscover/v1/publishservicelist';\r
-    private msbPublishServiceURL = '/api/mockarray';\r
-\r
-    constructor(private broadcastService: BroadcastService, private http: Http, private noticeService: NoticeService) {\r
-        this.broadcastService.planModel$.subscribe(planModel => {\r
-            planModel.configs.restConfigs.forEach(element => {\r
-                this.addRestConfig(element);\r
-            });\r
-        });\r
-        this.initSwaggerInfoByMSB();\r
-    }\r
-\r
-    public addRestConfig(config: RestConfig) {\r
-        const idSet = new Set<string>();\r
-        this.restConfigs.forEach(rc => {\r
-            idSet.add(rc.id);\r
-        });\r
-\r
-        if(idSet.has(config.id)) {\r
-            return false;\r
-        } else {\r
-            this.restConfigs.push(config);\r
-            return true;\r
-        }\r
-    }\r
-\r
-    public newRestConfig(): RestConfig {\r
-        const idSet = new Set<string>();\r
-        this.restConfigs.forEach(rc => {\r
-            idSet.add(rc.id);\r
-        });\r
-\r
-        let index = 0;\r
-        for(; index <= idSet.size; index++) {\r
-            if(!idSet.has(index + '')) {\r
-                break;\r
-            }\r
-        }\r
-\r
-        const restConfig = new RestConfig(index.toString(), 'new Config', '', '', '');\r
-        return restConfig;\r
-    }\r
-\r
-    // public initSwaggerInfo(restConfig: RestConfig) {\r
-    //     if (restConfig.dynamic && restConfig.definition) {\r
-    //         this.getDynamicSwaggerInfo(restConfig.definition).subscribe(response => restConfig.swagger = new Swagger(response));\r
-    //     } else {\r
-    //         restConfig.swagger = new Swagger(restConfig.swagger);\r
-    //     }\r
-    // }\r
-\r
-    public getRestConfigs() {\r
-        return this.restConfigs;\r
-    }\r
-\r
-    public getDynamicSwaggerInfo(url: string): Observable<any> {\r
-        const options: any = {\r
-            headers: {\r
-                Accept: 'application/json',\r
-            },\r
-        };\r
-        return this.http.get(url, options);\r
-    }\r
-\r
-    public getSwaggerInfo(id: string): Swagger {\r
-        const restConfig = this.restConfigs.find(tmp => tmp.id === id);\r
-        return restConfig === undefined ? undefined : restConfig.swagger;\r
-    }\r
-\r
-    public getResponseParameters(swagger: Swagger, interfaceUrl: string, operation: string): SwaggerResponse[] {\r
-        const path = swagger.paths[interfaceUrl];\r
-        const method: SwaggerMethod = path[operation];\r
-        let responses: SwaggerResponse[] = [];\r
-\r
-        for (const key of Object.keys(method.responses)) {\r
-            if (key.startsWith('20') && method.responses[key].schema && method.responses[key].schema.$ref) {\r
-                let response: SwaggerResponse = method.responses[key];\r
-                responses.push(response);\r
-            }\r
-        }\r
-\r
-        return responses;\r
-    }\r
-\r
-    public getDefinition(swagger: Swagger, position: string): SwaggerSchemaObject {\r
-        const definitionName = position.substring('#/definitions/'.length);\r
-\r
-        return swagger.definitions[definitionName];\r
-    }\r
-\r
-    private initSwaggerInfoByMSB(): void {\r
-        const options: any = {\r
-            headers: {\r
-                Accept: 'application/json',\r
-            }\r
-        };\r
-        let restConfigs = this.restConfigs;\r
-        this.http.get(this.runtimeURL).subscribe(runtimeResponse => {\r
-            const tenant = runtimeResponse.json().tenant;\r
-            console.log('Current namespace is:' + tenant);\r
-            this.http.get(this.msbPublishServiceURL, { params: { namespace: tenant } }).subscribe(serviceResponse => {\r
-                if (!Array.isArray(serviceResponse.json())) {\r
-                    return;\r
-                }\r
-                const services = serviceResponse.json();\r
-                const protocel = location.protocol.slice(0, location.protocol.length - 1);\r
-                const swaggerObservableArray: Observable<any>[] = [];\r
-                services.forEach(serviceInfo => {\r
-                    if ('REST' === serviceInfo.protocol && protocel === serviceInfo.publish_protocol) {\r
-                        // this service don't have sawgger file.\r
-                        if ('/activiti-rest' !== serviceInfo.publish_url) {\r
-                            const id = serviceInfo.serviceName + '.' + serviceInfo.version;\r
-                            this.addRestConfig(new RestConfig(id, serviceInfo.serviceName, serviceInfo.version, serviceInfo.publish_url, ''));\r
-                            let swaggerUrl = '';\r
-                            if (undefined !== serviceInfo.swagger_url && '' !== serviceInfo.swagger_url) {\r
-                                swaggerUrl = serviceInfo.publish_url + '/' + serviceInfo.swagger_url;\r
-                            } else {\r
-                                // default swagger url is: '/swagger.json'\r
-                                swaggerUrl = serviceInfo.publish_url + '/swagger.json';\r
-                            }\r
-                            swaggerObservableArray.push(this.http.get(swaggerUrl, options).timeout(5000).catch((error): Observable<any> => {\r
-                                console.log('Request swagger from:"' + swaggerUrl + '" faild!');\r
-                                return Observable.of(null);\r
-                            }));\r
-                        }\r
-                    }\r
-                });\r
-                Observable.forkJoin(swaggerObservableArray).subscribe(\r
-                    responses => {\r
-                        let deleteArray: number[] = [];\r
-                        responses.forEach((response, index) => {\r
-                            // mark http get failed request index or set the swagger into restConfigs\r
-                            if (null === response) {\r
-                                deleteArray.push(index);\r
-                            } else {\r
-                                try {\r
-                                    const swagger = response.json();\r
-                                    restConfigs[index].swagger = new Swagger(swagger);\r
-                                } catch (e) {\r
-                                    deleteArray.push(index);\r
-                                    console.warn('Do not support this sawgger file format:' + response.text());\r
-                                }\r
-                            }\r
-                        });\r
-                        console.log('Get all swagger file finish.');\r
-                        // delete failed request from all restConfigs array\r
-                        deleteArray.reverse();\r
-                        deleteArray.forEach(deleteIndex => {\r
-                            restConfigs.splice(deleteIndex, 1);\r
-                        });\r
-                        this.broadcastService.broadcast(this.broadcastService.updateModelRestConfig, restConfigs);\r
-                        console.log('Load all swagger finished.');\r
-                    }\r
-                );\r
-            });\r
-        });\r
-    }\r
-}\r
-\r
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+import { Injectable } from '@angular/core';
+import { Http, RequestOptionsArgs } from '@angular/http';
+import { Observable } from 'rxjs/Rx';
+import { isNullOrUndefined } from 'util';
+
+import { SwaggerMethod } from '../model/swagger';
+import { SwaggerResponseClass } from '../model/swagger';
+import { Swagger, SwaggerSchemaObject } from '../model/swagger';
+import { RestConfig } from '../model/rest-config';
+import { BroadcastService } from './broadcast.service';
+import { NoticeService } from './notice.service';
+import { SettingService } from './setting.service';
+
+@Injectable()
+export class RestService {
+    private restConfigs: RestConfig[] = [];
+    private runtimeURL = '/openoapi/catalog/v1/sys/config';
+    private msbPublishServiceURL = '/api/msdiscover/v1/publishservicelist';
+
+    constructor(private broadcastService: BroadcastService, private http: Http,
+        private noticeService: NoticeService, private settgingService: SettingService) {
+        this.settgingService.getSetting().subscribe(setting => {
+            if (true === setting.supportRestNode) {
+                this.initSwaggerInfo();
+            } else {
+                this.broadcastService.broadcast(this.broadcastService.updateModelRestConfig, null);
+            }
+        });
+    }
+
+    public getRestConfigs(): RestConfig[] {
+        return this.restConfigs;
+    }
+
+    public getRestConfig(id: string): RestConfig {
+        return this.restConfigs.find(tmp => tmp.id === id);
+    }
+
+    public getSwaggerInfo(id: string): Swagger {
+        const restConfig = this.restConfigs.find(tmp => tmp.id === id);
+        return restConfig === undefined ? undefined : restConfig.swagger;
+    }
+
+    public getResponseParameters(swagger: Swagger, interfaceUrl: string, operation: string): SwaggerResponseClass[] {
+        const path = swagger.paths[interfaceUrl];
+        const method: SwaggerMethod = path[operation];
+        let responses: SwaggerResponseClass[] = [];
+
+        for (const key of Object.keys(method.responses)) {
+            if (key.startsWith('20') && method.responses[key].schema && method.responses[key].schema.$ref) {
+                let response: SwaggerResponseClass = method.responses[key];
+                responses.push(response);
+            }
+        }
+
+        return responses;
+    }
+
+    public getDefinition(swagger: Swagger, position: string): SwaggerSchemaObject {
+        const definitionName = position.substring('#/definitions/'.length);
+        return swagger.definitions[definitionName];
+    }
+
+    private initSwaggerInfo(): void {
+        this.http.get(this.runtimeURL).subscribe(runtimeResponse => {
+            const tenant = runtimeResponse.json().tenant;
+            console.log('Current namespace is:' + tenant);
+            this.initSwaggerInfoByTenant(tenant);
+        }, error => {
+            console.warn('No tenant interface!');
+            this.initSwaggerInfoByTenant('');
+        });
+    }
+
+    private initSwaggerInfoByTenant(tenant: string): void {
+        this.http.get(this.msbPublishServiceURL, { params: { namespace: tenant } }).subscribe(serviceResponse => {
+            if (!Array.isArray(serviceResponse.json())) {
+                return;
+            }
+            const services = serviceResponse.json();
+            const protocel = location.protocol.slice(0, location.protocol.length - 1);
+            const swaggerObservableArray: Observable<any>[] = [];
+            services.forEach(serviceInfo => {
+                if ('REST' === serviceInfo.protocol && protocel === serviceInfo.publish_protocol) {
+                    // this service don't have sawgger file.
+                    if ('/activiti-rest' !== serviceInfo.publish_url) {
+                        const id = serviceInfo.serviceName + '.' + serviceInfo.version;
+                        this.restConfigs.push(new RestConfig(id, serviceInfo.serviceName, serviceInfo.version, serviceInfo.publish_url));
+                        let swaggerUrl = '';
+                        if (undefined !== serviceInfo.swagger_url && '' !== serviceInfo.swagger_url) {
+                            swaggerUrl = serviceInfo.publish_url + '/' + serviceInfo.swagger_url;
+                        } else {
+                            // default swagger url is: '/swagger.json'
+                            swaggerUrl = serviceInfo.publish_url + '/swagger.json';
+                        }
+                        const options: any = {
+                            headers: {
+                                Accept: 'application/json',
+                            }
+                        };
+                        swaggerObservableArray.push(this.http.get(swaggerUrl, options).timeout(5000).catch((error): Observable<any> => {
+                            console.log('Request swagger from:"' + swaggerUrl + '" faild!');
+                            return Observable.of(null);
+                        }));
+                    }
+                }
+            });
+            Observable.forkJoin(swaggerObservableArray).subscribe(
+                responses => {
+                    let deleteArray: number[] = [];
+                    responses.forEach((response, index) => {
+                        // mark http get failed request index or set the swagger into restConfigs
+                        if (null === response) {
+                            deleteArray.push(index);
+                        } else {
+                            try {
+                                const swagger = response.json();
+                                this.restConfigs[index].swagger = new Swagger(swagger);
+                            } catch (e) {
+                                deleteArray.push(index);
+                                console.warn('Do not support this sawgger file format:' + response.text());
+                            }
+                        }
+                    });
+                    console.log('Get all swagger file finish.');
+                    // delete failed request from all restConfigs array
+                    deleteArray.reverse();
+                    deleteArray.forEach(deleteIndex => {
+                        this.restConfigs.splice(deleteIndex, 1);
+                    });
+                    this.broadcastService.broadcast(this.broadcastService.updateModelRestConfig, this.restConfigs);
+                    console.log('Load all swagger finished.');
+                }
+            );
+        });
+
+    }
+}
+
index 0fe25d0..a85d2c2 100644 (file)
@@ -1,3 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
 import { TestBed, inject } from '@angular/core/testing';
 
 import { SettingService } from './setting.service';
index 558620f..266c553 100644 (file)
@@ -1,5 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
 import { Injectable } from '@angular/core';
-import { Observable } from "rxjs";
+import { Observable } from "rxjs/Rx";
 
 import { HttpService } from '../util/http.service';
 
@@ -14,8 +25,7 @@ export class SettingService {
         Accept: 'application/json',
       }
     };
-    // return this.http.get('assets/global-setting.json', options);
-    return this.http.get('/api/setting', options);
+    return this.http.get('assets/global-setting.json', options);
   }
 
 }
index 24fad5c..8128b44 100644 (file)
@@ -17,15 +17,15 @@ import { ValueSource } from '../model/value-source.enum';
 import { WorkflowUtil } from '../util/workflow-util';
 import { RestService } from './rest.service';
 import { Swagger } from "../model/swagger";
+import { ValueObject } from '../model/value-object';
+import { ValueType } from '../model/value-type.enum';
 
 @Injectable()
 export class SwaggerTreeConverterService {
 
   private swagger: Swagger;
 
-  constructor(private restService: RestService) {
-
-  }
+  constructor(private restService: RestService) { }
 
   public schema2TreeNode(swagger: Swagger, key: string | number, schema: any, value?: any): any {
     this.swagger = swagger;
@@ -52,12 +52,37 @@ export class SwaggerTreeConverterService {
     if (definition.$ref) {
       definition = this.restService.getDefinition(this.swagger, definition.$ref);
     }
+    let valueObject: ValueObject = { valueSource: ValueSource[ValueSource.string] };
+    if (undefined == value) {
+      valueObject.value = definition.default;
+      if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
+        valueObject.valueSource = ValueSource[ValueSource.Definition];
+      } else {
+        valueObject.valueSource = definition.type;
+      }
+    } else {
+      valueObject.valueSource = value.valueSource;
+      valueObject.value = undefined === value.value ? definition.default : value.value;
+    }
     if (definition.type === 'object') {
-      return this.getInitValue4Object(value);
+      // if (undefined == value) {
+      //   valueObject.value = definition.default;
+      //   if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
+      //     valueObject.valueSource = ValueSource[ValueSource.Definition];
+      //   } else {
+      //     valueObject.valueSource = definition.type;
+      //   }
+      // } else {
+      //   valueObject.valueSource = value.valueSource;
+      //   valueObject.value = undefined === value.value ? definition.default : value.value;
+      // }
+      return this.getInitValue4Object(valueObject);
     } else if (definition.type === 'array') {
-      return this.getInitValue4Array(value);
+      return this.getInitValue4Array(valueObject);
     } else { // primary type
-      return this.getInitValue4Primary(value);
+      // valueObject.value = undefined === value ? definition.default : value;
+      // valueObject.valueSource = definition.type;
+      return this.getInitValue4Primary(valueObject);
     }
   }
 
@@ -104,7 +129,7 @@ export class SwaggerTreeConverterService {
   private getInitValue4Primary(value: any) {
     const newValue = {
       value: '',
-      valueSource: ValueSource[ValueSource.String]
+      valueSource: ValueSource[ValueSource.string]
     };
 
     if (!value) {
diff --git a/sdc-workflow-designer-ui/src/app/services/tosca.service.spec.ts b/sdc-workflow-designer-ui/src/app/services/tosca.service.spec.ts
new file mode 100644 (file)
index 0000000..a54fba6
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { TestBed, inject } from '@angular/core/testing';
+
+import { ToscaService } from './tosca.service';
+
+describe('ToscaService', () => {
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      providers: [ToscaService]
+    });
+  });
+
+  it('should be created', inject([ToscaService], (service: ToscaService) => {
+    expect(service).toBeTruthy();
+  }));
+});
diff --git a/sdc-workflow-designer-ui/src/app/services/tosca.service.ts b/sdc-workflow-designer-ui/src/app/services/tosca.service.ts
new file mode 100644 (file)
index 0000000..dd62a71
--- /dev/null
@@ -0,0 +1,153 @@
+/**
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ *     ZTE - initial API and implementation and/or initial documentation
+ */
+import { Injectable } from '@angular/core';
+import { Observable } from "rxjs/Rx";
+
+import { NodeTemplate } from '../model/topology/node-template';
+import { SettingService } from './setting.service';
+import { HttpService } from '../util/http.service';
+import { BroadcastService } from './broadcast.service';
+
+@Injectable()
+export class ToscaService {
+  private nodeTemplate: NodeTemplate[] = [];
+  private topologyProperties: {
+    name: string;
+    value: string;
+  }[] = [];
+  private namespace;
+  private serviceTemplateId;
+  private repositoryURL;
+  constructor(private settingService: SettingService, private httpService: HttpService,
+    private broadcastService: BroadcastService) {
+    this.settingService.getSetting().subscribe(setting => {
+      if (true === setting.supportToscaNode) {
+        // todo: need to load tosca interface and tosca properties
+        this.initTOSCAInfo();
+      } else {
+        this.broadcastService.broadcast(this.broadcastService.updateModelToscaConfig, null);
+      }
+    });
+  }
+
+  public getNodeTemplate(): NodeTemplate[] {
+    return this.nodeTemplate;
+  }
+
+  public getTopologyProperties() {
+    return this.topologyProperties;
+  }
+
+  public initTOSCAInfo() {
+    this.getNodeTemplates().subscribe(nodes => {
+      if (0 === nodes.length) {
+        return;
+      }
+
+      const subscribes = nodes.map(node => this.loadTopologyProperties(node));
+      Observable.forkJoin(subscribes).map(nodesProperties => {
+        const allProperties: { name: string, value: string }[] = [];
+        nodesProperties.forEach((properties, index) => {
+          properties.forEach(property => {
+            // allProperties.push(nodes[index].name + '.' + property);
+            const propertyOption = {
+              name: `${nodes[index].name}.${property}`,
+              value: `[${nodes[index].name}].[${property}]`
+            };
+            allProperties.push(propertyOption);
+          });
+        });
+        return allProperties;
+      }).subscribe(allProperties => {
+        this.topologyProperties = allProperties;
+        this.broadcastService.broadcast(this.broadcastService.updateModelToscaConfig, this.topologyProperties);
+      });
+    });
+  }
+
+  public getNodeTemplates(): Observable<NodeTemplate[]> {
+    const url = 'servicetemplates/' + this.encode(this.namespace)
+      + '/' + this.encode(this.serviceTemplateId) + '/topologytemplate/';
+
+    return this.httpService.get(this.getFullUrl(url)).map(response => {
+      const nodeTemplates = [];
+      for (const key in response.nodeTemplates) {
+        if (response.nodeTemplates.hasOwnProperty(key)) {
+          const nodeTemplate = response.nodeTemplates[key];
+          nodeTemplates.push({
+            id: nodeTemplate.id,
+            type: nodeTemplate.type.replace(/^\{(.+)\}(.+)/, '$2'),
+            name: nodeTemplate.name,
+            namespace: nodeTemplate.type.replace(/^\{(.+)\}(.+)/, '$1'),
+          });
+        }
+      }
+      return nodeTemplates;
+    });
+  }
+
+  public loadTopologyProperties(nodeTemplate: NodeTemplate): Observable<string[]> {
+    const url = 'nodetypes/' + this.encode(nodeTemplate.namespace)
+      + '/' + this.encode(nodeTemplate.type) + '/propertiesdefinition/winery/list/';
+
+    return this.httpService.get(this.getFullUrl(url)).map(properties =>
+      properties.map(property => property.key));
+  }
+
+  public loadNodeTemplateInterfaces(nodeTemplate: NodeTemplate): Observable<string[]> {
+    const url = 'nodetypes/' + this.encode(nodeTemplate.namespace)
+      + '/' + this.encode(nodeTemplate.type) + '/interfaces/';
+
+    return this.httpService.get(this.getFullUrl(url));
+  }
+  public loadNodeTemplateOperations(nodeTemplate: NodeTemplate,
+    interfaceName: string): Observable<string[]> {
+    const url = 'nodetypes/' + this.encode(nodeTemplate.namespace)
+      + '/' + this.encode(nodeTemplate.type) + '/interfaces/' + this.encode(interfaceName) + '/operations/';
+
+    return this.httpService.get(this.getFullUrl(url));
+  }
+
+  public loadNodeTemplateOperationParameter(nodeTemplate: NodeTemplate,
+    interfaceName: string,
+    operation: string): Observable<any> {
+    const relativePath = 'nodetypes/' + this.encode(nodeTemplate.namespace) + '/' + this.encode(nodeTemplate.type)
+      + '/interfaces/' + this.encode(interfaceName) + '/operations/' + this.encode(operation) + '/';
+
+    // input parameters
+    const inputObservable = this.httpService
+      .get(this.getFullUrl(relativePath + 'inputparameters'));
+
+    // output parameters
+    const outputObservable = this.httpService
+      .get(this.getFullUrl(relativePath + 'outputparameters'));
+
+    return Observable.forkJoin([inputObservable, outputObservable]).map(params => {
+      return {
+        input: params[0],
+        output: params[1],
+      };
+    });
+  }
+
+  private decode(param: string): string {
+    return decodeURIComponent(decodeURIComponent(param));
+  }
+
+  private encode(param: string): string {
+    return encodeURIComponent(encodeURIComponent(param));
+  }
+
+  private getFullUrl(relativePath: string) {
+    return this.repositoryURL + relativePath;
+  }
+}
diff --git a/sdc-workflow-designer-ui/src/app/services/workflow.service.ts b/sdc-workflow-designer-ui/src/app/services/workflow.service.ts
deleted file mode 100644 (file)
index 127629c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/**\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- */\r
-\r
-import { Injectable } from '@angular/core';\r
-import { DataService } from "./data/data.service";\r
-import { Observable } from "rxjs/Observable";\r
-import { PlanModel } from "../model/plan-model";\r
-import { BroadcastService } from "./broadcast.service";\r
-\r
-/**\r
- * ModelService\r
- * provides all operations about plan model.\r
- */\r
-@Injectable()\r
-export class WorkflowService {\r
-\r
-    public workflows = new Map<string, any>();\r
-    public planModel: PlanModel;\r
-    private planName : string;\r
-\r
-    constructor(private broadcastService: BroadcastService, private dataAccessService: DataService) {\r
-        this.broadcastService.workflows$.subscribe(workflows => this.workflows = workflows);\r
-        this.broadcastService.planModel$.subscribe(workflow => this.planModel = workflow);\r
-    }\r
-\r
-    public save() {\r
-        console.log(this.planModel);\r
-        console.log(JSON.stringify(this.planModel));\r
-        this.broadcastService.broadcast(this.broadcastService.saveEvent, {"name": this.planName, "planModel": this.planModel});\r
-    }\r
-\r
-    public getPlanName(planId: string): string {\r
-        const planInfo = this.workflows.get(planId);\r
-        return planInfo ? planInfo.planName: null;\r
-    }\r
-\r
-    public getPlanModel(planId: string): PlanModel {\r
-        const planInfo = this.workflows.get(planId);\r
-        return planInfo ? planInfo.plan: null;\r
-    }\r
-\r
-    public getWorkflows(): Map<string, any> {\r
-\r
-        return this.workflows;\r
-    }\r
-\r
-    public addWorkflow() {\r
-        this.workflows.set(this.getPlanId(), {"planName": "newPlan", "plan": new PlanModel()});\r
-        this.broadcastWorkflows();\r
-    }\r
-\r
-    public deleteWorkflow(planId: string): PlanModel {\r
-        this.workflows.delete(planId);\r
-        this.broadcastWorkflows();\r
-\r
-        return undefined;\r
-    }\r
-\r
-    public broadcastWorkflows() {\r
-        this.broadcastService.broadcast(this.broadcastService.workflows, this.workflows);\r
-    }\r
-\r
-    private getPlanId(): string {\r
-        for(let index=0; index <= this.workflows.size; index++) {\r
-            if(!this.workflows.has(index + "")) {\r
-                return index + "";\r
-            }\r
-        }\r
-    }\r
-}\r
diff --git a/sdc-workflow-designer-ui/src/favicon.ico b/sdc-workflow-designer-ui/src/favicon.ico
deleted file mode 100644 (file)
index 8081c7c..0000000
Binary files a/sdc-workflow-designer-ui/src/favicon.ico and /dev/null differ
diff --git a/sdc-workflow-designer-ui/src/ngict-component.css b/sdc-workflow-designer-ui/src/ngict-component.css
deleted file mode 100644 (file)
index 32582bb..0000000
+++ /dev/null
@@ -1,1908 +0,0 @@
-/***main***/
-body,
-button,
-input,
-optgroup,
-select,
-textarea,
-.tooltip {
-  font-family: "Microsoft yahei", Segoe UI, Arial !important;
-  font-size: 12px;
-  color: #333;
-}
-body {
-  background-color: transparent;
-  font-size: 14px;
-}
-[class^="col-"],
-[class*="col-"] {
-  float: left;
-}
-.clearfix:after,
-.container:after,
-.container-fluid:after,
-.row:after,
-.form-horizontal .form-group:after,
-.btn-toolbar:after,
-.btn-group-vertical > .btn-group:after,
-.nav:after,
-.navbar:after,
-.navbar-header:after,
-.navbar-collapse:after,
-.pager:after,
-.panel-body:after,
-.modal-footer:after {
-  clear: both;
-}
-.clearfix:before,
-.clearfix:after,
-.container:before,
-.container:after,
-.container-fluid:before,
-.container-fluid:after,
-.row:before,
-.row:after,
-.form-horizontal .form-group:before,
-.form-horizontal .form-group:after,
-.btn-toolbar:before,
-.btn-toolbar:after,
-.btn-group-vertical > .btn-group:before,
-.btn-group-vertical > .btn-group:after,
-.nav:before,
-.nav:after,
-.navbar:before,
-.navbar:after,
-.navbar-header:before,
-.navbar-header:after,
-.navbar-collapse:before,
-.navbar-collapse:after,
-.pager:before,
-.pager:after,
-.panel-body:before,
-.panel-body:after,
-.modal-footer:before,
-.modal-footer:after {
-  content: " ";
-  display: table;
-}
-.label,
-label {
-  font-weight: 400;
-}
-*:focus {
-  outline: 0;
-}
-a {
-  color: #00abff;
-  text-decoration: none ;
-  cursor: pointer;
-}
-a:hover {
-  color: #00a3f5;
-  text-decoration: underline;
-}
-.border-box {
-  border: 1px solid #ddd;
-}
-/***icon***/
-[class^="ict-"],
-[class*=" ict-"] {
-  padding-right: 3px;
-}
-/***color***/
-.red {
-  background-color: #ff5b55;
-  color: #fff;
-}
-.red:hover {
-  background-color: #f55651;
-  color: #fff;
-}
-.green {
-  background-color: #5fcc4a;
-  color: #fff;
-}
-.green:hover {
-  background-color: #329d96;
-  color: #fff;
-}
-.gold {
-  background-color: #c0af69;
-  color: #fff;
-}
-.gold:hover {
-  background-color: #ad9a4d;
-  color: #fff;
-}
-.over-grey {
-  background-color: transparent;
-  color: #00abff;
-  border: 0;
-}
-.over-grey:hover {
-  background-color: #f8f8f8;
-}
-.over-grey:focus:active {
-  background-color: #f2f2f2;
-}
-.grey {
-  background-color: #fff;
-  color: #a5a5a5;
-  border: 1px solid #eee;
-}
-.grey:hover {
-  background-color: #fcfcfc;
-}
-.grey-disabled,
-.grey-disabled:hover {
-  border: 1px solid #c6c6c6;
-  color: #c6c6c6;
-  background-color: #fff;
-}
-.dark-grey {
-  background-color: #333;
-  color: #fff;
-}
-.dark-grey:hover {
-  background-color: #101010;
-  color: #fff;
-}
-.oes-red {
-  color: #ff5b55;
-}
-.bg-danger {
-  background-color: #ff5b55 !important;
-}
-.oes-red-bg {
-  background-color: #ff5b55;
-  color: #fff;
-}
-.oes-red-bg:hover {
-  background-color: #f55651;
-  color: #fff;
-}
-.oes-red-bg:active {
-  background-color: #eb534d;
-  color: #fff;
-}
-.oes-green {
-  color: #5fcc4a;
-}
-.oes-green-bg {
-  background-color: #73cf22;
-  color: #fff;
-}
-.oes-green-bg:hover {
-  background-color: #6cc41f;
-  color: #fff;
-}
-.oes-green-bg:active {
-  background-color: #67ba1e;
-  color: #fff;
-}
-.oes-yellow {
-  color: #ffc766;
-}
-.oes-yellow-bg {
-  background-color: #f7c515;
-  color: #fff;
-}
-.oes-yellow-bg:hover {
-  background-color: #edbe13;
-  color: #fff;
-}
-.oes-yellow-bg:active {
-  background-color: #e3b612;
-  color: #fff;
-}
-.oes-grey {
-  color: #a5a5a5;
-}
-.oes-grey-bg {
-  background-color: #a5a5a5;
-  color: #fff;
-}
-.oes-grey-bg:hover {
-  background-color: #949393;
-  color: #fff;
-}
-.oes-grey-bg:active {
-  background-color: #848383;
-  color: #fff;
-}
-.blue {
-  background-color: #fff;
-  color: #1991c5;
-}
-.blue:hover {
-  background-color: #e8f3fd;
-  color: #3366cc;
-}
-.blue.selected {
-  border: 0;
-  background-color: #00abff;
-  color: #fff;
-}
-.blue.selected:hover {
-  border: 0;
-  background-color: #00abff;
-  color: #fff;
-}
-.blue1 {
-  background-color: #00abff;
-  color: #fff;
-  border: 1px solid #00abff;
-}
-.blue1:hover {
-  background-color: #00a3f5;
-  color: #fff;
-  border: 1px solid #00a3f5;
-}
-.blue1:active {
-  background-color: #009ceb;
-}
-.blue1:focus {
-  background-color: #00abff;
-  color: #fff;
-  border: 1px solid #00abff;
-}
-.blue1:focus:hover {
-  background-color: #00a3f5;
-  color: #fff;
-  border: 1px solid #00a3f5;
-}
-.blue1:focus:active {
-  background-color: #009ceb;
-}
-.blue1-active {
-  background-color: #00abff !important;
-  color: #fff  !important;
-  border: 1px solid #00abff !important;
-}
-.blue1-active:hover {
-  background-color: #00a3f5 !important;
-  color: #fff  !important;
-  border: 1px solid #00a3f5 !important;
-}
-.blue1-active:focus {
-  background-color: #00abff !important;
-  color: #fff  !important;
-  border: 1px solid #00abff !important;
-}
-.blue1-active:focus:hover {
-  background-color: #00a3f5 !important;
-  color: #fff  !important;
-  border: 1px solid #00a3f5 !important;
-}
-.white {
-  background-color: #fff;
-  border: 1px solid #eee;
-  color: #00abff;
-}
-.white:hover {
-  background-color: #fcfcfc;
-}
-.white:active {
-  background-color: #f8f8f8;
-}
-.white.active {
-  background-color: #00abff;
-  color: #fff;
-  border-color: #00abff;
-}
-.white:focus {
-  background-color: #fff;
-  border: 1px solid #eee;
-  color: #00abff;
-  outline: none;
-}
-.white:focus:hover {
-  background-color: #fcfcfc;
-}
-.white:focus:hover:active {
-  background-color: #f8f8f8;
-}
-.white:focus.active {
-  background-color: #00abff;
-  color: #fff;
-  border-color: #00abff;
-}
-.blue1-icons {
-  color: #009ceb;
-}
-.blue1-icons:hover {
-  color: #00a3f5;
-}
-.oes-font1,
-.oes-font1:active,
-.oes-font1:focus {
-  color: #c2c6c9;
-}
-.oes-font2,
-.oes-font2:active,
-.oes-font2:focus {
-  color: #777;
-}
-.oes-font3,
-.oes-font3:active,
-.oes-font3:focus {
-  color: #4d5761;
-}
-.oes-font4,
-.oes-font4:active,
-.oes-font4:focus {
-  color: #333;
-}
-/***
-Responsive & Scrollable Tables
-***/
-.table-scrollable {
-  width: 100%;
-  overflow-x: auto;
-  overflow-y: hidden;
-  border: 1px solid #ddd;
-}
-.table-scrollable > .table {
-  width: 100% !important;
-  margin: 0 !important;
-  margin-bottom: 0;
-  background-color: #fff;
-}
-.table-scrollable > .table-bordered {
-  border: 0;
-}
-.table-scrollable > .table-bordered > thead > tr > th:first-child,
-.table-scrollable > .table-bordered > tbody > tr > th:first-child,
-.table-scrollable > .table-bordered > tfoot > tr > th:first-child,
-.table-scrollable > .table-bordered > thead > tr > td:first-child,
-.table-scrollable > .table-bordered > tbody > tr > td:first-child,
-.table-scrollable > .table-bordered > tfoot > tr > td:first-child {
-  border-left: 0;
-}
-.table-scrollable > .table-bordered > thead > tr > th:last-child,
-.table-scrollable > .table-bordered > tbody > tr > th:last-child,
-.table-scrollable > .table-bordered > tfoot > tr > th:last-child,
-.table-scrollable > .table-bordered > thead > tr > td:last-child,
-.table-scrollable > .table-bordered > tbody > tr > td:last-child,
-.table-scrollable > .table-bordered > tfoot > tr > td:last-child {
-  border-right: 0;
-}
-.table-scrollable > .table-bordered > thead > tr:last-child > th,
-.table-scrollable > .table-bordered > tbody > tr:last-child > th,
-.table-scrollable > .table-bordered > tfoot > tr:last-child > th,
-.table-scrollable > .table-bordered > thead > tr:last-child > td,
-.table-scrollable > .table-bordered > tbody > tr:last-child > td,
-.table-scrollable > .table-bordered > tfoot > tr:last-child > td {
-  border-bottom: 0;
-}
-/*table*/
-table {
-  font-size: 12px;
-}
-.table-hover > tbody > tr:hover > td,
-.table-hover > tbody > tr:hover > th {
-  background: #ebf6fd;
-}
-.dataTables_length,
-.dataTables_info,
-.dataTables_paginate {
-  font-size: 12px;
-  color: #7c868d;
-  display: inline-block;
-}
-.dataTables_length {
-  margin-right: 9px;
-}
-.dataTables_info {
-  margin-right: 10px;
-  color: #4d5761;
-}
-.dataTables_length select {
-  margin-left: 1px;
-  margin-right: 1px;
-  width: 42px;
-  height: 30px;
-  border-color: #ddd;
-  color: #7c868d;
-}
-.dataTables_paginate {
-  vertical-align: top;
-}
-.dataTables_paginate input {
-  border-color: #ddd !important;
-  width: 42px !important;
-  height: 30px !important;
-  margin-left: 6px!important;
-  margin-right: 6px!important;
-  color: #7c868d;
-}
-.dataTables_paginate .pagination-panel a {
-  border: 1px solid #ddd;
-  width: 26px;
-  height: 30px;
-  opacity: 1;
-  margin-left: 6px;
-  vertical-align: top;
-  cursor: pointer;
-  color: #7c868d;
-}
-.dataTables_wrapper > div > div {
-  float: right;
-  margin-bottom: 10px;
-  margin-top: 10px;
-}
-table th {
-  font-weight: normal;
-  font-size: 12px;
-}
-.table thead th {
-  border-bottom: 0;
-  color: #8b8b8b;
-}
-.table th {
-  border-top: 0;
-}
-table .heading {
-  font-size: 12px;
-  background: #fff !important;
-  font-weight: normal;
-}
-table tr:nth-of-type(odd) {
-  background: #f9f9f9;
-}
-table tr:nth-of-type(even) {
-  background: #fff;
-}
-table tr td label {
-  cursor: pointer;
-}
-.table-btn span {
-  padding-left: 5px;
-  padding-right: 5px;
-}
-.table-bordered > thead > tr > th,
-.table-bordered > thead > tr > td {
-  border-bottom-width: 1px;
-}
-table tr td .btn-xs {
-  margin-bottom: 3px;
-  margin-top: 3px;
-}
-/* oes-table */
-.oes-table.light .oes-th {
-  padding-bottom: 15px !important;
-}
-.oes-table .oes-th {
-  padding-bottom: 10px !important;
-}
-/*.oes-table.card  tr:nth-of-type(odd){
-  background-color:#fff !important;
-}*/
-.oes-table.card tr:nth-of-type(odd):hover {
-  background-color: #ebf6fd !important;
-}
-.oes-table.card tr td:first-child,
-.oes-table.card tr th:first-child {
-  text-align: center;
-}
-.oes-table.card .title {
-  font-weight: normal;
-}
-.oes-table .filter span.filterToggle {
-  width: 30px !important;
-  height: 30px !important;
-}
-.oes-table input[type="checkbox"] {
-  margin-right: 0;
-}
-.oes-page-item .oes-page-link {
-  height: 28px !important;
-}
-.oes-filters .oes-th {
-  padding-bottom: 2px !important;
-}
-.oes-pagination {
-  margin-top: 0 !important;
-}
-.oes-table .filter span.filterToggle {
-  height: 30px !important;
-}
-.oes-table label,
-.oes-table input[type="checkbox"] {
-  margin-bottom: 0;
-}
-.oes-table .innerTable tr:nth-of-type(odd) {
-  background-color: #fff !important;
-}
-/*ng2-smart-table*/
-.ng2-smart-table.light .ng2-smart-th,
-.ng2-smart-table .ng2-smart-th {
-  padding-bottom: 10px !important;
-}
-.ng2-smart-table .card tr:nth-of-type(odd) {
-  background-color: #fff !important;
-}
-.ng2-smart-table .card tr:nth-of-type(odd):hover {
-  background-color: #ebf6fd !important;
-}
-.ng2-smart-table .card tr td:first-child,
-.ng2-smart-table .card tr th:first-child {
-  text-align: center;
-}
-.ng2-smart-table .card .title {
-  font-weight: normal;
-}
-.ng2-smart-table .filter span.filterToggle {
-  width: 30px !important;
-  height: 30px !important;
-}
-.ng2-smart-table input[type="checkbox"] {
-  margin-right: 0;
-}
-.ng2-smart-page-item .ng2-smart-page-link {
-  height: 28px !important;
-}
-.ng2-smart-filters .ng2-smart-th {
-  padding-bottom: 2px !important;
-}
-.ng2-smart-pagination {
-  margin-top: 0 !important;
-}
-.ng2-smart-table .filter span.filterToggle {
-  height: 30px !important;
-}
-.ng2-smart-table label,
-.ng2-smart-table input[type="checkbox"] {
-  margin-bottom: 0;
-}
-.ng2-smart-table .innerTable tr:nth-of-type(odd) {
-  background-color: #fff !important;
-}
-/***form***/
-.form {
-  padding: 0 !important;
-}
-.form-group .multiRow {
-  margin-bottom: 15px;
-}
-.form-group .multiRow:last-child {
-  margin-bottom: 5px;
-}
-.form-group {
-  font-size: 12px;
-}
-.form-group .btn {
-  font-size: 14px;
-}
-.form-group .btn-s {
-  font-size: 12px;
-}
-.form-group .ict-helpTip {
-  font-size: 18px;
-  color: #bababa;
-  margin-left: 10px;
-  vertical-align: text-bottom;
-}
-.form-group .ict-helpTip:hover {
-  color: #00abff;
-}
-.form-group.equal-group .form-control {
-  display: block;
-}
-.form-group.equal-group .form-control:first-child {
-  margin-bottom: 5px;
-}
-.form-body {
-  padding: 15px;
-}
-.form-actions .btn {
-  font-size: 14px;
-}
-.form-actions.nobg {
-  background-color: transparent;
-}
-.form-actions.top {
-  margin-top: 0;
-  margin-bottom: 20px;
-  border-top: 0;
-  border-bottom: 1px solid #e5e5e5;
-}
-.form-control {
-  font-size: 12px;
-  display: inline-block;
-}
-.form-actions .btnGroup {
-  padding-left: 0;
-}
-.form-actions.fluid > [class^="col-"] {
-  padding-left: 13px;
-}
-.form-actions:before,
-.form-actions:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-.form-actions:after {
-  clear: both;
-}
-.form-section {
-  margin: 30px 0px 25px 0px;
-  padding-bottom: 5px;
-  border-bottom: 1px solid #eee;
-}
-.form .form-section:first-child {
-  margin-top: 5px;
-}
-.help-inline {
-  font-size: 13px;
-  color: #737373;
-  display: inline-block;
-  padding: 5px;
-}
-.submBtn {
-  /*text-align: center;*/
-}
-.subm-iconMargin {
-  margin-left: -40px;
-}
-.subm-margin {
-  margin-left: -40px;
-}
-.form-actions.right {
-  padding-left: 0;
-  padding-right: 10px;
-  text-align: right;
-}
-.form-actions.left {
-  padding-left: 10px;
-  padding-right: 0;
-  text-align: left;
-}
-.help-block {
-  margin-top: 5px;
-  margin-bottom: 5px;
-  color: #a94442 !important;
-}
-.form-inline input {
-  margin-bottom: 0px !important;
-}
-.form-horizontal .control-label {
-  text-align: right;
-}
-.form-group .control-label {
-  padding-top: 3px;
-}
-.form-control-static {
-  font-size: 14px;
-  padding-top: 7px;
-}
-.control-label .required {
-  color: #e02222;
-  font-size: 12px;
-  padding-left: 2px;
-}
-.form-control:focus {
-  -webkit-box-shadow: none;
-  box-shadow: none;
-}
-select.form-control,
-.form-control {
-  padding: 4px 12px;
-  border-radius: 2px;
-  height: 30px;
-  /* width:400px;*/
-  border-color: #ddd;
-}
-select.form-control:not([size]):not([multiple]) {
-  height: 30px ;
-}
-/***checkbox&radio***/
-/* Checkbox */
-.form-group .checkbox {
-  padding-left: 0;
-}
-.checkbox-list > label {
-  display: block;
-}
-.checkbox-list > label.checkbox-inline {
-  display: inline-block;
-}
-.checkbox-list > label.checkbox-inline:first-child {
-  padding-left: 0;
-}
-/* Radios */
-input[type="radio"] {
-  cursor: pointer;
-}
-.radio-list > label {
-  display: block;
-}
-.radio-list > label.radio-inline {
-  display: inline-block;
-}
-.radio-list > label.radio-inline:first-child {
-  padding-left: 0;
-}
-.form-horizontal .radio-list .radio {
-  padding-top: 1px;
-}
-.form-horizontal .radio-list > label {
-  margin-bottom: 0;
-}
-.form-horizontal .radio > span {
-  margin-top: 2px;
-}
-input[type="checkbox"]:focus,
-input[type="radio"]:focus {
-  outline: 0;
-  -webkit-box-shadow: none;
-  box-shadow: none;
-  border: 0;
-}
-.raw-container {
-  font-size: 0;
-  position: relative;
-}
-.raw-container input[type="checkbox"],
-.raw-container input[type="radio"] {
-  position: absolute;
-  z-index: -1;
-  opacity: 0;
-}
-.raw-container input[type="checkbox"] + .checkbox-substitute + span,
-.raw-container input[type="radio"] + .radio-substitute + span {
-  font-weight: normal;
-  font-size: 12px;
-  line-height: 12px;
-  cursor: pointer;
-  vertical-align: middle;
-}
-.raw-container input[type="checkbox"] + .checkbox-substitute {
-  position: relative;
-  display: inline-block;
-  cursor: pointer;
-  height: 14px;
-  width: 14px;
-  border: 1px solid #ccc;
-  border-radius: 2px;
-  vertical-align: middle;
-  margin-right: 6px;
-}
-.raw-container input[type="checkbox"] + .checkbox-substitute:hover {
-  border-color: #00abff;
-}
-.raw-container input[type="checkbox"]:checked + .checkbox-substitute {
-  border-color: #00abff;
-  background-color: #00abff;
-}
-.raw-container input[type="checkbox"]:checked + .checkbox-substitute::after {
-  content: '';
-  position: absolute;
-  display: block;
-  width: 6px;
-  height: 10px;
-  border: solid #fff;
-  border-width: 0 2px 2px 0;
-  transform: rotate(45deg);
-  left: 3px;
-  top: 0;
-}
-.raw-container input[type="checkbox"][disabled] + .checkbox-substitute {
-  background-color: #efefef;
-  cursor: auto;
-  border-color: #ccc;
-}
-.raw-container input[type="checkbox"]:checked[disabled] + .checkbox-substitute {
-  background-color: #efefef;
-  cursor: auto;
-  border-color: #ccc;
-}
-.raw-container input[type="checkbox"]:checked[disabled] + .checkbox-substitute::after {
-  border: 1px solid #ccc;
-  border-width: 0 2px 2px 0;
-}
-.raw-container input[type="checkbox"]:checked.portion + .checkbox-substitute {
-  background-color: #97dbfc;
-  border-color: #97dbfc;
-}
-.raw-container input[type="radio"] + .radio-substitute {
-  position: relative;
-  display: inline-block;
-  cursor: pointer;
-  height: 14px;
-  width: 14px;
-  border: 1px solid #ccc;
-  border-radius: 14px;
-  vertical-align: middle;
-  margin-right: 6px;
-}
-.raw-container input[type="radio"] + .radio-substitute:hover {
-  border-color: #00abff;
-}
-.raw-container input[type="radio"]:checked + .radio-substitute {
-  border-color: #00abff;
-  border-width: 4px;
-}
-.raw-container input[type="radio"][disabled] + .radio-substitute {
-  border-color: #ccc;
-  background-color: #efefef;
-  cursor: auto;
-}
-.raw-container input[type="radio"]:checked [disabled] + .radio-substitute {
-  border-color: #ccc;
-  cursor: auto;
-}
-/***input***/
-::-webkit-input-placeholder {
-  color: #bcbcbc !important;
-}
-:-moz-placeholder {
-  /* Mozilla Firefox 4 to 18 */
-  color: #bcbcbc !important;
-}
-::-moz-placeholder {
-  /* Mozilla Firefox 19+ */
-  color: #bcbcbc !important;
-}
-input:-ms-input-placeholder {
-  color: #bcbcbc !important;
-}
-input::-webkit-input-placeholder {
-  color: #bcbcbc !important;
-}
-/*group*/
-.input-group-btn-vertical.fa {
-  font-size: 12px;
-}
-.input-group.spinner .btn {
-  min-width: 20px !important;
-  height: 16px;
-}
-.spinner {
-  width: 60px !important;
-  margin-left: 10px;
-  margin-right: 30px;
-}
-.spinner input {
-  text-align: right;
-}
-.input-group-btn-vertical {
-  position: relative;
-  white-space: nowrap;
-  width: 1%;
-  vertical-align: middle;
-  display: table-cell;
-}
-.input-group-btn-vertical > .btn {
-  display: block;
-  float: none;
-  width: 100%;
-  max-width: 100%;
-  padding: 6px;
-  margin-left: -1px;
-  position: relative;
-  border-radius: 0;
-}
-.input-group-btn-vertical > .btn {
-  min-width: 20px;
-}
-.input-group-btn-vertical > .btn:first-child {
-  border-top-right-radius: 4px;
-}
-.input-group-btn-vertical > .btn:last-child {
-  margin-top: -2px;
-  border-bottom-right-radius: 4px;
-}
-.input-group-btn-vertical i {
-  position: absolute;
-  top: 0;
-  left: 6px;
-}
-/*.input-group .form-control {
-    height: 26px !important;   
-}*/
-.input-group {
-  /* width:400px;*/
-  font-size: 0;
-}
-.input-group .form-control {
-  display: inline-block;
-}
-.input-group .form-control:hover,
-.input-group .form-control:focus:hover {
-  z-index: 2;
-}
-.input-group .input-group-btn {
-  z-index: 0;
-}
-/*html滑块组件*/
-input[type="range"] {
-  margin-top: 2px;
-  background-color: #f0f3f9;
-  border: 1px solid #ccd6e8;
-  border-radius: 15px;
-  width: 400px;
-  -webkit-appearance: none;
-  height: 15px;
-}
-input[type="range"]::-webkit-slider-thumb {
-  -webkit-appearance: none;
-  cursor: pointer;
-  top: -5px;
-  height: 28px;
-  width: 15px;
-  transform: translateY(-4px);
-  background: none repeat scroll 0 0 #f0f3f9;
-  background-color: #9cc2cb;
-  border-radius: 20px;
-}
-input[type="range"]:focus {
-  outline: none;
-}
-/*search*/
-.input-group .btn {
-  min-width: 40px;
-  padding-top: 3px;
-}
-/***tab***/
-.nav-tabs {
-  border: 0;
-  font-weight: bold;
-}
-.nav-tabs > li.active > a,
-.nav-tabs > li.active > a:hover,
-.nav-tabs > li.active > a:focus {
-  border: 0;
-}
-.nav-tabs > li > a {
-  border-radius: 0;
-  font-weight: bold;
-  border: 0;
-  margin-right: 0;
-}
-.nav > li > a:hover,
-.nav > li > a:focus {
-  background-color: transparent;
-}
-.nav-tabs.boder-tab > li.active > a,
-.nav-tabs.boder-tab > div > li.active > a {
-  border: 1px solid #ddd;
-  border-bottom: 0;
-}
-.nav-tabs-content {
-  border: 1px solid #ddd;
-}
-/***tab***/
-.nav-tabs.tabset > li.active,
-.nav-tabs.tabset > li.active:hover,
-.nav-tabs.tabset > li.active:focus {
-  border: 0;
-  border-top: 2px solid #00abff;
-}
-.nav-tabs > div > li.active,
-.nav-tabs > div > li.active:hover,
-.nav-tabs > div > li.active:focus {
-  border: 0;
-  background-color: #fcfcfc;
-  border-top: 2px solid #00abff;
-}
-ul.nav.nav-tabs {
-  background-color: transparent;
-}
-.nav-tabs > div > li > a:hover {
-  background-color: transparent;
-  border-bottom: 1px transparent;
-}
-.nav-tabs .nav-link {
-  border-top-right-radius: 0;
-  border-top-left-radius: 0;
-  color: #777;
-}
-.nav-tabs .nav-link:hover {
-  background-color: transparent;
-  border-color: transparent;
-  color: #777;
-}
-.nav-tabs .nav-link:focus {
-  border-left-color: transparent;
-  border-right-color: transparent;
-}
-.boder-tab ul.nav.nav-tabs {
-  background-color: #fff;
-}
-.boder-tab ul.nav.nav-tabs .nav-link:hover {
-  border-bottom: 1px solid #ddd ;
-  background-color: #fcfcfc;
-}
-.boder-tab ul.nav.nav-tabs .nav-link.active:hover {
-  border-bottom: 0 ;
-}
-.nav-tabs {
-  border: 0;
-  font-weight: normal;
-}
-.nav-tabs > li > a {
-  border-radius: 0;
-  font-weight: normal;
-  border: 0;
-  margin-right: 0;
-}
-.nav-tabs > li > a:hover,
-.nav-tabs > li > a:focus {
-  background-color: transparent;
-}
-.nav-tabs .nav-link.active {
-  border: 0;
-  border-top: 2px solid #00abff;
-  background-color: #fff;
-}
-.nav-tabs .nav-link.active:hover {
-  background-color: #fff;
-  border-top: 2px solid #00abff;
-}
-.nav-tabs .nav-link.disabled {
-  border-top: 0;
-  color: #c2c6c9;
-}
-.nav-tabs .nav-link.disabled:hover,
-.nav-tabs .nav-link.disabled:focus {
-  background-color: transparent;
-  color: #c2c6c9;
-}
-.boder-tab > .nav-tabs > .nav-item > .nav-link.active,
-.less-border > .nav-tabs > .nav-item > .nav-link.active {
-  border: 1px solid #ddd;
-  border-top: 2px solid #00abff;
-  border-bottom: 0;
-}
-.boder-tab .tab-pane.active {
-  border: 1px solid #ddd;
-}
-.tab-pane.active {
-  padding: 15px;
-}
-.nav-pills .nav-link.active,
-.nav-pills .nav-item.show .nav-link {
-  color: #fff;
-  cursor: default;
-  background-color: #00abff;
-}
-.less-border .tab-pane.active {
-  border-top: 1px solid #ddd;
-  border-left: 0;
-  border-right: 0;
-  border-bottom: 0;
-}
-/***button***/
-button {
-  font-size: 14px;
-}
-.btn {
-  min-width: 80px;
-  letter-spacing: 1px;
-  padding-top: 4px !important;
-  padding-bottom: 4px !important;
-  height: 30px;
-  font-size: 14px;
-  cursor: pointer;
-  line-height: 1.42857143;
-}
-.btnGroup .btn,
-.btnGroup a {
-  margin-right: 10px;
-}
-.btnGroup a:last-child,
-.btnGroup .btn:last-child {
-  margin-right: 0;
-}
-.btnGroup .sub-btn {
-  /*float:right;
-       width: 400px;*/
-  /*text-align: right;*/
-}
-.pagination-panel .btn {
-  min-width: 4px;
-}
-.btn.dropdown-toggle,
-.btn-group .btn.dropdown-toggle,
-.btn:hover,
-.btn:disabled,
-.btn[disabled],
-.btn:focus,
-.btn:active,
-.btn.active {
-  outline: none !important;
-  background-image: none !important;
-  filter: none;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  text-shadow: none;
-}
-.btn-s {
-  height: 26px;
-  line-height: 14px;
-  font-size: 12px;
-  cursor: pointer;
-}
-.btn-s:hover {
-  text-decoration: none ;
-}
-.btn-s:focus {
-  outline: 0;
-}
-.btn-xs {
-  line-height: 1.2;
-  padding-top: 3px;
-  padding-bottom: 3px;
-  font-size: 12px;
-  cursor: pointer;
-}
-.btn-xs:hover {
-  text-decoration: none ;
-}
-.btn-xs:focus {
-  outline: 0;
-}
-/***btn-group***/
-.btn-group .blue1-active {
-  border-left: #a4d7f7 1px solid !important;
-}
-.btn-group .blue1-active:hover {
-  border-left: #1289d6 1px solid !important;
-}
-.btn-group .white.btn.active,
-.btn-group .white.btn-s.active {
-  border-left: #6ac7f5 1px solid !important;
-}
-/***toolbar & icons ***/
-.toolbar span {
-  padding: 5px;
-  font-size: 20px;
-  cursor: pointer;
-  color: #00abff;
-  border: 1px solid transparent;
-}
-.toolbar span:hover {
-  color: #00a3f5;
-  border: 1px solid #cbdfec;
-}
-.toolbar i.seperate-vertical {
-  padding: 0;
-  border-right: 1px solid #ddd;
-  margin-right: 8px;
-  margin-left: 4px;
-}
-/*btn-link*/
-.btn-link {
-  color: #ccc;
-}
-.btn-link:hover {
-  color: #1798eb;
-}
-/***radius***/
-.radius-l {
-  border-radius: 20px;
-}
-.radius-m {
-  border-radius: 8px;
-}
-.radius-s {
-  border-radius: 4px;
-}
-.radius-xs {
-  border-radius: 3px;
-}
-/***progress***/
-.progress,
-.progress-s {
-  border: 0;
-  background-image: none !important;
-  filter: none !important;
-  -webkit-box-shadow: none !important;
-  -moz-box-shadow: none !important;
-  box-shadow: none !important;
-  opacity: 0.7;
-}
-.progress {
-  height: 8px;
-  display: inline-block;
-}
-.progress-s {
-  height: 2px;
-}
-.progress > .progress-bar-success {
-  background-color: #00abff;
-}
-.progress-bar {
-  height: 8px;
-}
-.progress > .bg-success {
-  background-color: #00abff !important;
-}
-.oes-progressbar .progress {
-  display: inline-block;
-}
-.progress-rate {
-  vertical-align: sub;
-  margin-left: 5px;
-}
-.progress-error {
-  display: inline-block;
-  width: 16px;
-  height: 16px;
-  border-radius: 16px;
-  border: 1px solid #ff5b55;
-  font-size: 12px;
-  color: #ff5b55;
-  text-align: center;
-  line-height: 1;
-  margin-left: 5px;
-}
-.progress-error::before {
-  content: "!";
-}
-.progressbar-s .progress {
-  height: 2px;
-}
-/***separator & title***/
-.separator-line {
-  height: 1px;
-  width: 100%;
-  background: #ddd;
-  overflow: hidden;
-  margin-bottom: 15px;
-  opacity: 0.7;
-}
-.separator {
-  opacity: 0.7;
-}
-.separator:hover {
-  opacity: 1;
-}
-.separator-line-dashed {
-  margin-top: 15px;
-  height: 1px;
-  border-bottom: 1px dashed #ddd;
-  margin-bottom: 15px;
-  overflow: hidden;
-  width: 100%;
-}
-.titlefont {
-  font-size: 14px;
-  margin-top: 15px;
-  margin-bottom: 5px;
-}
-.form-title,
-.form-title-foldable {
-  border-left: 3px solid #00abff;
-}
-.form-title {
-  padding: 1px 2px 1px 5px;
-  margin-bottom: 15px;
-  color: #7c868d;
-  font-size: 14px;
-}
-.form-title-foldable {
-  padding: 1px 2px 1px 5px;
-  margin-bottom: 15px;
-  font-size: 14px;
-}
-.form-title-foldable span {
-  margin-right: 10px;
-  cursor: pointer;
-}
-.form-title-foldable span[class^="ict-"] {
-  font-size: 12px;
-  color: #009ceb;
-}
-/***ztree***/
-.ztree {
-  padding: 15px 30px 0 5px;
-}
-.ztree * {
-  font-family: "microsoft yahei";
-  font-size: 12px;
-}
-.ztree li a {
-  width: auto;
-  padding-right: 5px;
-  height: 25px;
-  border: 1px solid #fff;
-  padding-left: 5px;
-}
-.ztree li a:hover {
-  border: 1px solid #ddd !important;
-}
-.ztree li > span {
-  margin-top: 5px !important;
-}
-.ztree li span.button.chk {
-  width: 13px;
-  height: 13px;
-  margin-left: 10px;
-  cursor: auto;
-}
-.ztree li span.button.add {
-  margin-left: 2px;
-  margin-right: 4px;
-  background-position: -144px 0;
-  vertical-align: top;
-  *vertical-align: middle;
-  float: right;
-}
-.ztree li span.button.edit {
-  margin-right: 4px;
-  background-position: -110px -48px;
-  vertical-align: top;
-  *vertical-align: middle;
-  float: right;
-}
-.ztree li span.button.remove {
-  margin-right: 4px;
-  background-position: -110px -64px;
-  vertical-align: top;
-  *vertical-align: middle;
-  float: right;
-}
-.ztree li a.curSelectedNode {
-  height: 25px;
-  border: 1px #accbdd solid !important;
-}
-.ztree-select .ztree li a {
-  border: 1px solid #fff !important;
-}
-.ztree-select .ztree li a:hover {
-  border: 1px #ddd solid !important;
-}
-/***tip***/
-.terminology {
-  color: #468ECE;
-  border-bottom: 1px #468ECE dotted;
-}
-.General-tip {
-  height: 20px;
-  width: 20px;
-  background-color: #fff;
-  border: 1px #5b9bd1 solid;
-  padding-bottom: 5px;
-  padding-left: 5px;
-  border-radius: 20px;
-  margin-top: 5px;
-}
-.General-tip span {
-  font-size: 15px;
-  text-align: center;
-  color: #5b9bd1;
-  line-height: 1.1;
-}
-.General-tip:hover {
-  border: 1px #2a6496 solid;
-  cursor: pointer;
-}
-.General-tip:hover span {
-  color: #2a6496;
-}
-/*tip-box*/
-.frmTipBoxTransition {
-  -webkit-transition: -webkit-transform 0.3s ease-out;
-  -o-transition: -o-transform 0.3s ease-out;
-  transition: transform 0.3s ease-out;
-  -webkit-transform: translate(0, 50%);
-  -ms-transform: translate(0, 50%);
-  -o-transform: translate(0, 50%);
-  transform: translate(0, 50%);
-}
-#frmTipBox {
-  position: absolute;
-  width: 400px;
-  margin: 10px auto;
-  left: 30%;
-  right: 30%;
-  top: 14px;
-}
-/*alert*/
-.alert {
-  padding: 12px 15px;
-  max-width: 600px;
-  text-align: left;
-  -webkit-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
-  -moz-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
-  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
-}
-/*     
-.alert-success {
-    color: #fff;
-    background-color: #73cf22;   
-    border-color:#73cf22;
-}
-
-.alert-info {
-    color: #fff;
-    background-color: #00abff;   
-       border-color:#00abff;   
-}
-
-.alert-warning {
-    color: #fff;
-    background-color: #f7c515; 
-       border-color:#f7c515;           
-}
-
-.alert-danger {
-    color: #fff;
-    background-color: #ff5b55;
-       border-color:#ff5b55;   
-}*/
-.close {
-  color: #f2f2f2;
-  font-size: 16px;
-}
-.close:hover,
-.close:focus {
-  color: inherit;
-  outline: 0;
-}
-.alert-success {
-  color: #56963e;
-  background-color: #edfbe8;
-  border-color: #d5eccc;
-  opacity: 0.85;
-}
-.alert-info {
-  color: #5090c3;
-  background-color: #ecf7fd;
-  border-color: #bce1f1;
-  opacity: 0.85;
-}
-.alert-warning {
-  color: #bf880a;
-  background-color: #fff8e9;
-  border-color: #f5e1b8;
-  opacity: 0.85;
-}
-.alert-danger {
-  color: #df4364;
-  background-color: #fbf0f1;
-  border-color: #f3d9da;
-  opacity: 0.85;
-}
-.close {
-  color: #333;
-  font-size: 1rem;
-}
-/*tooltip*/
-.tooltip.show {
-  font-size: 12px;
-  opacity: 1;
-}
-.tooltip.show .tooltip-inner {
-  background-color: #4d5761;
-  border-radius: 4px;
-  padding: 5px 8px;
-}
-.tooltip.tooltip-top .tooltip-inner::before,
-.tooltip.bs-tether-element-attached-bottom .tooltip-inner::before {
-  border-top-color: #4d5761;
-}
-.tooltip.tooltip-right .tooltip-inner::before,
-.tooltip.bs-tether-element-attached-left .tooltip-inner::before {
-  border-right-color: #4d5761;
-}
-.tooltip.tooltip-bottom .tooltip-inner::before,
-.tooltip.bs-tether-element-attached-top .tooltip-inner::before {
-  border-bottom-color: #4d5761;
-}
-.tooltip.tooltip-left .tooltip-inner::before,
-.tooltip.bs-tether-element-attached-right .tooltip-inner::before {
-  border-left-color: #4d5761;
-}
-/*modal*/
-.modal-footer {
-  border-top: 0;
-  margin-top: 0;
-  padding-top: 0;
-}
-.modal-content {
-  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
-}
-.modal-title {
-  font-size: 16px;
-}
-.modal {
-  z-index: 10000;
-}
-.modal .modal-dialog {
-  max-width: 1000px;
-}
-.modal .close {
-  color: #bbb;
-  font-size: 20px;
-  text-shadow: none;
-  width: 24px;
-  height: 24px;
-  background: #fff;
-  border-radius: 20px;
-  padding-bottom: 2px;
-}
-.modal .close:hover {
-  background: #f2f2f2;
-}
-.modal .modal-header {
-  border-bottom: 0;
-}
-.modal .alert-modal.row {
-  margin-left: 30px;
-  margin-bottom: 30px;
-  text-align: left;
-}
-.modal .alert-modal.row .tip-img {
-  display: inline-block;
-  width: 52px;
-  height: 52px;
-  border-radius: 50px;
-  font-size: 45px;
-  text-align: center;
-  line-height: 1;
-  margin-right: 15px;
-}
-.modal .alert-modal.row .tip-img::before {
-  content: "!";
-}
-.modal .alert-modal.row .warning {
-  border: 3px solid #ffbb51;
-  color: #ffbb51;
-}
-.modal .alert-modal.row .error {
-  border: 3px solid #ff5b55;
-  color: #ff5b55;
-}
-.modal .alert-modal.row .tip-info {
-  width: 300px;
-}
-.modal .alert-modal.row .tip-info .alert-title {
-  font-size: 16px;
-  color: #7c868d;
-}
-.modal .alert-modal.row .tip-info .alert-result {
-  font-size: 14px;
-  color: #7c868d;
-}
-.modal .modal-btn {
-  float: right;
-  font-size: 0;
-}
-.oes-modal .modal-footer {
-  display: block;
-}
-.modal-body {
-  padding-top: 0;
-}
-.modal-body .form-group:last-child,
-.modal-body form:last-child {
-  margin-bottom: 0;
-}
-/***pagination***/
-.page-item.active .page-link {
-  background-color: #1798eb;
-  border-color: #1798eb;
-}
-/***wizard***/
-.form-wizard .nav > li > a {
-  padding-bottom: 0;
-}
-.wizard-body .button-next.disabled,
-.wizard-body .button-previous.disabled {
-  display: none ;
-}
-.wizard-body .nav .step {
-  background: none !important;
-}
-.form-wizard .progress {
-  margin-bottom: 30px;
-  margin-top: 10px;
-  height: 4px;
-  width: 100%;
-}
-.form-wizard .steps {
-  background-color: #fff ;
-  background-image: none ;
-  filter: none ;
-  border: 0px;
-  box-shadow: none ;
-}
-.form-wizard .steps li a {
-  background-color: #fff ;
-  background-image: none ;
-  filter: none;
-  border: 0px;
-  box-shadow: none ;
-  color: #7c868d;
-}
-.form-wizard .steps:hover {
-  background: none;
-}
-.form-wizard .step:hover {
-  text-decoration: none;
-}
-.form-wizard .step .number {
-  background-color: #ddd;
-  color: #fff;
-  display: inline-block;
-  text-align: center !important;
-  font-size: 14px;
-  font-weight: 300;
-  padding-top: 2px;
-  margin-right: 10px;
-  height: 24px;
-  width: 24px;
-  -webkit-border-radius: 50% !important;
-  -moz-border-radius: 50% !important;
-  border-radius: 50% !important;
-}
-.form-wizard .step .desc {
-  display: inline-block;
-  font-size: 14px;
-  font-weight: 300;
-  color: #7c868d;
-}
-.form-wizard .step i {
-  display: none;
-}
-.form-wizard .active .step .number {
-  background-color: #35aa47;
-  color: #fff;
-}
-.form-wizard .active .step .desc {
-  color: #333;
-  font-weight: 400;
-}
-.form-wizard .done .step .number {
-  background-color: #73cf22 ;
-  color: #fff;
-}
-.form-wizard .done .step .desc {
-  font-weight: 400;
-}
-.form-wizard .done .step .form-wizard .done .step i {
-  font-size: 12px;
-  font-weight: normal;
-  color: #999;
-  display: inline-block;
-}
-.form-wizard .steps > li.active > a.step .number {
-  background-color: #00abff;
-}
-@media (min-width: 600px) and (max-width: 1280px) {
-  .form-wizard .step .desc {
-    margin-top: 10px;
-    display: block;
-  }
-}
-@media (max-width: 600px) {
-  .form-wizard .steps > li > a {
-    text-align: left;
-  }
-}
-@media (min-width: 600px) {
-  .nav-justified > li {
-    display: table-cell;
-    width: 1%;
-  }
-}
-.oes-wizard .nav.nav-pills.steps li {
-  text-align: center;
-}
-.oes-wizard .nav.nav-pills.steps li .desc {
-  font-size: 14px;
-}
-.oes-wizard .nav.nav-pills.steps li .oes-wizard .form-wizard .step .number {
-  padding-top: 1px;
-}
-/***popover***/
-ngb-popover-window.popover.show {
-  color: #333;
-  border: 1px solid #ddd;
-}
-.popover.popover-top::after,
-.popover.bs-tether-element-attached-bottom::after {
-  border-top-color: #fff;
-}
-.popover.popover-top::before,
-.popover.bs-tether-element-attached-bottom::before {
-  border-top-color: #ddd;
-}
-.popover.popover-left::after,
-.popover.bs-tether-element-attached-right::after {
-  border-left-color: #fff;
-}
-.popover.popover-left::before,
-.popover.bs-tether-element-attached-right::before {
-  border-left-color: #ddd;
-}
-.popover.popover-right::after,
-.popover.bs-tether-element-attached-left::after {
-  border-right-color: #fff;
-}
-.popover.popover-right::before,
-.popover.bs-tether-element-attached-left::before {
-  border-right-color: #ddd;
-}
-.popover.popover-bottom::after,
-.popover.bs-tether-element-attached-top::after {
-  border-bottom-color: #fff;
-}
-.popover.popover-bottom::before,
-.popover.bs-tether-element-attached-top::before {
-  border-bottom-color: #ddd;
-}
-.popover {
-  background-color: #fff;
-  font-family: "Microsoft yahei", Segoe UI, Arial !important;
-  font-size: 12px;
-  border-color: #ddd;
-  -webkit-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);
-  -moz-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);
-  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);
-}
-.popover .popover-title {
-  background-color: #fff;
-  border-bottom: 1px solid #ddd;
-}
-.popover .popover-content {
-  background-color: #fff;
-}
-/***collapse***/
-#collapseExample .card {
-  position: relative;
-  width: 100%;
-  height: 100px;
-}
-/*.collapse-bottom .card span.pop-trgl {
-    position: absolute;
-    top: -10px;
-    left: 20px;
-    width: 0;
-    height: 0;
-    border-style: solid;
-    border-width: 0 10px 10px 10px;
-    border-color: transparent transparent #cbc5c5 transparent;
-}
-.collapse-bottom .card span.pop-trgl i {
-    position: absolute;
-    left: -9px;
-    top: 1px;
-    width: 0;
-    height: 0;
-    border-style: solid;
-    border-width: 0 9px 9px 9px;
-    border-color: transparent transparent #fff transparent;
-}
-
-.collapse-top .card span.pop-trgl {
-    position: absolute;
-    bottom: -10px;
-    left: 20px;
-    width: 0;
-    height: 0;
-    border-style: solid;
-    border-width: 0 10px 10px 10px;
-    border-color: transparent transparent #cbc5c5 transparent;
-       transform:rotate(180deg);
-}
-.collapse-top .card span.pop-trgl i {
-    position: absolute;
-    left: -9px;
-    top: 1px;
-    width: 0;
-    height: 0;
-    border-style: solid;
-    border-width: 0 9px 9px 9px;
-    border-color: transparent transparent #fff transparent;
-}*/
-.collapse-top .card-block {
-  padding: 0;
-}
-.collapse-top .card {
-  margin-bottom: 5px;
-  padding: 15px;
-}
-.collapse-bottom .card {
-  margin-top: 5px;
-  padding: 15px;
-}
-/***select-box with icon***/
-.iconselect-box .col-xs-1 {
-  width: 15px;
-  padding: 110px 0 0 0;
-}
-.iconPosition > div {
-  margin: 20px 0px 0px 0px;
-}
-/***.dropdown-item***/
-.dropdown-item {
-  color: #4d5761;
-}
-.dropdown-item:focus,
-.dropdown-item:hover,
-.dropdown-item:active {
-  background-color: #f8f8f8;
-  outline: none;
-  color: #4d5761;
-}
-.dropdown-menu {
-  border: 0;
-  -webkit-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);
-  -moz-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);
-  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);
-}
-.btn-xs + .dropdown-menu .dropdown-item {
-  font-size: 12px;
-}
-/***datepicker***/
-.oes-dp-header {
-  border-bottom: 0 !important;
-}
-.oes-dp-header select.custom-select {
-  color: #777;
-  margin-top: 5px;
-  width: 45%;
-  margin-right: 5px;
-  font-size: 12px;
-}
-.oes-date-range-picker .ngb-dp-weekday {
-  color: #777;
-}
-.oes-date-range-picker .ngb-dp-header {
-  border-bottom: 0 !important;
-}
-.oes-dp-months.pb-1 {
-  padding-left: 15px !important;
-  padding-right: 15px !important;
-}
-.oes-dp-months.pb-1 .oes-dp-day,
-.oes-dp-months.pb-1 .oes-dp-weekday,
-.oes-dp-months.pb-1 .oes-dp-week-number {
-  width: 40px;
-  height: 40px;
-}
-.oes-dp-week.d-flex {
-  color: #777;
-}
-.font-italic {
-  font-style: normal;
-}
-.oes-dp-weekday.text-info {
-  color: #777 !important;
-}
-.oes-dp-day .btn-secondary {
-  border-radius: 20px !important;
-}
-.oes-dp-day .bg-primary {
-  background-color: #00abff !important;
-  border-radius: 20px !important;
-}
-.dropdown-menu .oes-dp-day {
-  font-size: 14px;
-}
-.dropdown-menu .oes-dp-weekday.small {
-  font-size: 80%;
-}
-.oes-dp-month-name.text-center {
-  color: #777;
-  font-size: 14px !important;
-}
-.custom-day.weekend {
-  background-color: #00abff !important;
-  height: 2rem;
-  line-height: 1.8;
-  border-radius: 20px !important;
-}
-.custom-day.weekend:hover {
-  background-color: #00a3f5 !important;
-}
-/***oes-upload***/
-.oes-uploder .progress {
-  width: 300px;
-}