[
  {
    "path": ".gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\n### JetBrains template\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff:\n.idea\n.idea/**/workspace.xml\n.idea/**/tasks.xml\n.idea/dictionaries\n\n# webpack stuff\ndist\n\n# node_modules\nnode_modules\n\n# semantic\nsemantic\n\n\n\n# Sensitive or high-churn files:\n.idea/**/dataSources/\n.idea/**/dataSources.ids\n.idea/**/dataSources.xml\n.idea/**/dataSources.local.xml\n.idea/**/sqlDataSources.xml\n.idea/**/dynamic.xml\n.idea/**/uiDesigner.xml\n\n# Gradle:\n.idea/**/gradle.xml\n.idea/**/libraries\n\n# Mongo Explorer plugin:\n.idea/**/mongoSettings.xml\n\n## File-based project format:\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\n/out/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\ndocumentation/"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) [year] [fullname]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "\n# NGX Dynamic Dashboard Framework\n\n## Natural Language Processing (NLP) integration\n![Image of Main Screen](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/nlp.gif)\n\n## Sample Board 1\n![Image of Main Screen](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/images/sb1.png)\n\n## Add Board and Gadget \n![Image of Add Gadget To Screen](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/add.gif)\n\n## Layout\n![Image Layout](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/layout.gif)\n\n## Example JSON document\nThe following JSON document describes a single board along with its layout, gadgets and their properites.\n\n```json\n{\n  \"board\": [\n    {\n      \"title\": \"Board Sample 1\",\n      \"structure\": \"3-6-3\",\n      \"id\": 9,\n      \"boardInstanceId\": 1,\n      \"rows\": [\n        {\n          \"columns\": [\n            {\n              \"styleClass\": \"three wide\",\n              \"gadgets\": [\n                {\n                  \"componentType\": \"NewsGadgetComponent\",\n                  \"name\": \"News\",\n                  \"description\": \"What's new\",\n                  \"icon\": \"images/news.png\",\n                  \"instanceId\": 1500253814523,\n                  \"tags\": [\n                    {\n                      \"facet\": \"Informational\",\n                      \"name\": \"news\"\n                    },\n                    {\n                      \"facet\": \"List\",\n                      \"name\": \"news\"\n                    }\n                  ],\n                  \"config\": {\n                    \"propertyPages\": [\n                      {\n                        \"displayName\": \"Run\",\n                        \"groupId\": \"run\",\n                        \"position\": 10,\n                        \"properties\": [\n                          {\n                            \"value\": \"news\",\n                            \"key\": \"endpoint\",\n                            \"label\": \"News URL\",\n                            \"required\": false,\n                            \"order\": 3,\n                            \"controlType\": \"dynamicdropdown\"\n                          },\n                          {\n                            \"value\": \"News\",\n                            \"key\": \"title\",\n                            \"label\": \"Title\",\n                            \"required\": false,\n                            \"order\": 1,\n                            \"controlType\": \"textbox\"\n                          },\n                          {\n                            \"value\": 2,\n                            \"key\": \"instanceId\",\n                            \"required\": false,\n                            \"order\": -1,\n                            \"controlType\": \"hidden\"\n                          }\n                        ]\n                      }\n                    ]\n                  }\n                }\n              ]\n            },\n            {\n              \"styleClass\": \"six wide\",\n              \"gadgets\": [\n                {\n                  \"componentType\": \"CPUGadgetComponent\",\n                  \"name\": \"CPU Chart\",\n                  \"description\": \"Monitors CPU utilization for application.\",\n                  \"icon\": \"images/cpu.png\",\n                  \"instanceId\": 1499912922910,\n                  \"tags\": [\n                    {\n                      \"facet\": \"Performance\",\n                      \"name\": \"real-time\"\n                    },\n                    {\n                      \"facet\": \"Chart\",\n                      \"name\": \"bar\"\n                    }\n                  ],\n                  \"config\": {\n                    \"propertyPages\": [\n                      {\n                        \"displayName\": \"Run\",\n                        \"groupId\": \"run\",\n                        \"position\": 10,\n                        \"properties\": [\n                          {\n                            \"value\": \"CPU Utilization\",\n                            \"key\": \"title\",\n                            \"label\": \"Title\",\n                            \"required\": false,\n                            \"order\": 1,\n                            \"controlType\": \"textbox\"\n                          },\n                          {\n                            \"value\": \"Carlosappliance - Process Monitor\",\n                            \"key\": \"endpoint\",\n                            \"label\": \"API Endpoints\",\n                            \"required\": false,\n                            \"order\": 3,\n                            \"controlType\": \"dynamicdropdown\"\n                          },\n                          {\n                            \"value\": 999,\n                            \"key\": \"instanceId\",\n                            \"required\": false,\n                            \"order\": -1,\n                            \"controlType\": \"hidden\"\n                          }\n                        ]\n                      },\n                      {\n                        \"displayName\": \"Chart\",\n                        \"groupId\": \"chart\",\n                        \"position\": 11,\n                        \"properties\": [\n                          {\n                            \"value\": true,\n                            \"key\": \"chart_properties\",\n                            \"label\": \"Show chart details\",\n                            \"required\": false,\n                            \"order\": 3,\n                            \"controlType\": \"checkbox\"\n                          }\n                        ]\n                      }\n                    ]\n                  }\n                },\n                {\n                  \"componentType\": \"TrendGadgetComponent\",\n                  \"name\": \"Trend\",\n                  \"description\": \"General trends.\",\n                  \"icon\": \"images/trend.png\",\n                  \"instanceId\": 1499912901569,\n                  \"tags\": [\n                    {\n                      \"facet\": \"Performance\",\n                      \"name\": \"trend\"\n                    },\n                    {\n                      \"facet\": \"Chart\",\n                      \"name\": \"area\"\n                    }\n                  ],\n                  \"config\": {\n                    \"propertyPages\": [\n                      {\n                        \"displayName\": \"Run\",\n                        \"groupId\": \"run\",\n                        \"position\": 10,\n                        \"properties\": [\n                          {\n                            \"value\": \"Devappliance\",\n                            \"key\": \"endpoint\",\n                            \"label\": \"API Endpoints\",\n                            \"required\": false,\n                            \"order\": 2,\n                            \"controlType\": \"dynamicdropdown\"\n                          },\n                          {\n                            \"value\": \"Trend\",\n                            \"key\": \"title\",\n                            \"label\": \"Title\",\n                            \"required\": false,\n                            \"order\": 1,\n                            \"controlType\": \"textbox\"\n                          },\n                          {\n                            \"value\": 2,\n                            \"key\": \"instanceId\",\n                            \"required\": false,\n                            \"order\": -1,\n                            \"controlType\": \"hidden\"\n                          }\n                        ]\n                      },\n                      {\n                        \"displayName\": \"Chart\",\n                        \"groupId\": \"chart\",\n                        \"position\": 11,\n                        \"properties\": [\n                          {\n                            \"value\": true,\n                            \"key\": \"chart_properties\",\n                            \"label\": \"Show chart details\",\n                            \"required\": false,\n                            \"order\": 3,\n                            \"controlType\": \"checkbox\"\n                          }\n                        ]\n                      }\n                    ]\n                  }\n                }\n              ]\n            },\n            {\n              \"styleClass\": \"three wide\",\n              \"gadgets\": []\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}\n```\n\n## Alert/Notification\n![Image Notification](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/notification.gif)\n\n## Sample Realtime Web Socket Based Gadget\n![Image of Add Gadget To Screen](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/websocket-realtime.gif)\n\n## Sample Board 2\n![Image of Main Screen](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/images/sb2.png)\n\n## Drag and Drop\n![Image of Add Board To Screen](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/drag-drop.gif)\n\n## Facet Filter\n![Image of Filter Board To Screen](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/filter.gif)\n\n\n\n> Note: This project is under heavy construction and is not intended for general production use yet. As such, we are not accepting bugs at the moment and documentation is quite lacking.\n\nThis is an angular (ngx) based dashboard framework that is inspired by JIRA's dashboard implementation and https://github.com/angular-dashboard-framework/angular-dashboard-framework\n\nThe primary projects leveraged:\n* Angular  - https://angularjs.org/\n* ngx-charts (angular based d3 charts) - https://github.com/swimlane/ngx-charts\n* Semantic-UI - https://semantic-ui.com/\n* ng2-dnd drag and drop - https://github.com/akserg/ng2-dnd\n* AI Natural Language Processing - The board includes two options for AI, Wit.Ai and IBM Watson.\n* Wit.ai - Natural Language Processing site has been integrated via JSONP\n* IBM Watson - IBM Watson does not support JSONP so the code relies on a backend implementation of the IBM Watson SDK.\nI offer sample backend code based on Spring Boot within the comments of the Runtime Service\n\nFeatures:\n* Leverages Angular's dynamic data driven forms approach for gadget property pages and properties - https://angular.io/guide/dynamic-form\n* Dynamic component strategy for creating gadget instances during runtime - https://angular.io/guide/dynamic-component-loader\n* Faceted gadget search approach leveraging tags\n* Support multiple board creation\n* Drag and Drop support\n* Multiple Data Source/Endpoint management\n* Web Socket support\n* Completely customizable and configurable\n\n# Getting Started Developing a Gadget\n\nThe code includes a very simple Todo gadget that can be used as an example for getting started developing your own gadget. The following steps uses that Todo Gadget as a reference. You focus on defining the gadget and the rest of the framework will deal with making it available to the Add Gadget Modal, drag and drop, instance creation, tracking, persistence and cleanup, etc.\n\n## Define the Gadget Component, Service and View\n\n* Todo Component  [todo-gadget.component.ts](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/app/gadgets/todo/todo-gadget.component.ts)\n* Todo View [view.html](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/app/gadgets/todo/view.html)\n* Todo Service [service.ts](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/app/gadgets/todo/service.ts)\n* Sample mock service data [todo-model.json](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/assets/api/todo-model.json)\n\n## Define the gadget's model\n\nThe model is used to dynamically create and render the gadget and its property page forms. This model is an entry into a model array used for all gadgets. You will simply add an entry to the model's array. See the Todo entry.\nAdd an entry for the gadget in the library model array [gadget-library-model.json](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/assets/api/gadget-library-model.json)\n\n## Add the gadget entry to the gadget factory class\n\nAdd an entry for your gadget in the factory gadget class [gadget-factory.ts](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/app/add-gadget/gadget-factory.ts)\n\n## Gadget Icon\n\nDefine an image/icon for your gadget [todo.png](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/assets/images/todo.png)\n\n## Gadget Module References\n\n* Import the gadget's component into the board module [board.module.ts](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/app/board/board.module.ts)\n* Import the gadget's service into the grid module [grid.module.ts](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/app/grid/grid.module.ts)\n* Import the gadget's component and service into the gadget module [gadget.module.ts](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework/blob/master/src/app/gadgets/gadget.module.ts)\n\n![Todo Gadget](https://github.com/catalogicsoftware/Angular-2-Dashboard-Framework/blob/master/src/assets/documentation/gifs/TodoGadget.gif)\n\n# NgADF\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.x.\n\n## Setup\n\nClone this repository then run `npm install`\n\n## Development server\n\nRun `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.\n\n\n## Build\n\nRun `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--aot --prod` flag for ahead of time compilation and production mode. \n\nThe title of that issue suggests an issue with AOT but in my testing `--prod` seems to be the problem. \n\n## Running unit tests\n\nRun `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Running end-to-end tests\n\nRun `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).\nBefore running the tests make sure you are serving the app via `ng serve`.\n\n## Source Code Documentation\n\nThis project uses the compodoc project : https://github.com/compodoc/compodoc\n\nRun `npm install -g @compodoc/compodoc` to install compodoc globally\nRun `compodoc -p tsconfig.json -n 'NGX Dynamic Dashboard Framework'` to generate the documentation. It will be placed in the documentation folder\nRun `compodoc -s` to serve up the documentation site at http://localhost:8080\n\n## Spring Boot Backend Project\n\nThere is an accompanying java based backend project that serves up some of the endpoints used by the board.\n\n[https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework-microservice](https://github.com/catalogicsoftware/ngx-dynamic-dashboard-framework-microservice)\n\nIt is a maven based project so you will need to do the following: \n* Install and configure Maven. \n* Copy the dist directory produced from this project's build into the \n`static` folder of the microservice project. \n* Build the microservice project using `<directory path to maven bin folder>/mvn install`  from within the project's root directory. \n* Launch the microservice over the default port: `http://localhost:8080` using `java -jar <path to the microservice root folder>/target/ngxdd-x.y.z.jar`\n\n\n## Further help\n\nTo 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).\n\n"
  },
  {
    "path": "angular.json",
    "content": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"ng-adf\": {\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"projectType\": \"application\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist\",\n            \"index\": \"src/index.html\",\n            \"main\": \"src/main.ts\",\n            \"tsConfig\": \"src/tsconfig.app.json\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"assets\": [\n              \"src/assets\",\n              \"src/favicon.ico\"\n            ],\n            \"styles\": [\n              \"src/styles.css\",\n              \"node_modules/semantic-ui/dist/semantic.min.css\",\n              \"node_modules/ng2-dnd/bundles/style.css\",\n              \"node_modules/material-design-icons/iconfont/material-icons.css\"\n            ],\n            \"scripts\": [\n              \"node_modules/jquery/dist/jquery.min.js\",\n              \"node_modules/semantic-ui/dist/semantic.min.js\",\n              \"node_modules/d3-shape/dist/d3-shape.min.js\"\n            ]\n          },\n          \"configurations\": {\n            \"production\": {\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"extractCss\": true,\n              \"namedChunks\": false,\n              \"aot\": true,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true,\n              \"fileReplacements\": [\n                {\n                  \"replace\": \"src/environments/environment.ts\",\n                  \"with\": \"src/environments/environment.prod.ts\"\n                }\n              ]\n            }\n          }\n        },\n        \"serve\": {\n          \"builder\": \"@angular-devkit/build-angular:dev-server\",\n          \"options\": {\n            \"browserTarget\": \"ng-adf:build\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"browserTarget\": \"ng-adf:build:production\"\n            }\n          }\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular-devkit/build-angular:extract-i18n\",\n          \"options\": {\n            \"browserTarget\": \"ng-adf:build\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"src/test.ts\",\n            \"karmaConfig\": \"./karma.conf.js\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"src/tsconfig.spec.json\",\n            \"scripts\": [\n              \"node_modules/jquery/dist/jquery.min.js\",\n              \"node_modules/semantic-ui/dist/semantic.min.js\",\n              \"node_modules/d3-shape/build/d3-shape.min.js\"\n            ],\n            \"styles\": [\n              \"src/styles.css\",\n              \"node_modules/semantic-ui/dist/semantic.min.css\",\n              \"node_modules/ng2-dnd/bundles/style.css\"\n            ],\n            \"assets\": [\n              \"src/assets\",\n              \"src/favicon.ico\"\n            ]\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"src/tsconfig.app.json\",\n              \"src/tsconfig.spec.json\"\n            ],\n            \"exclude\": []\n          }\n        }\n      }\n    },\n    \"ng-adf-e2e\": {\n      \"root\": \"\",\n      \"sourceRoot\": \"e2e\",\n      \"projectType\": \"application\",\n      \"architect\": {\n        \"e2e\": {\n          \"builder\": \"@angular-devkit/build-angular:protractor\",\n          \"options\": {\n            \"protractorConfig\": \"./protractor.conf.js\",\n            \"devServerTarget\": \"ng-adf:serve\"\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"e2e/tsconfig.e2e.json\"\n            ],\n            \"exclude\": []\n          }\n        }\n      }\n    }\n  },\n  \"defaultProject\": \"ng-adf\",\n  \"cli\": {\n    \"warnings\": {\n      \"typescriptMismatch\": false\n    }\n  },\n  \"schematics\": {\n    \"@schematics/angular:component\": {\n      \"prefix\": \"app\",\n      \"styleext\": \"css\"\n    },\n    \"@schematics/angular:directive\": {\n      \"prefix\": \"app\"\n    }\n  }\n}"
  },
  {
    "path": "build.sh",
    "content": "#!/bin/bash\n\n#ng config -g cli.warnings.versionMismatch false\n\nnpm install\n\nng build --prod --aot\n\n"
  },
  {
    "path": "e2e/app.e2e-spec.ts",
    "content": "import { NgADFPage } from './app.po';\n\ndescribe('ng-adf App', () => {\n  let page: NgADFPage;\n\n  beforeEach(() => {\n    page = new NgADFPage();\n  });\n\n  it('should display message saying app works', () => {\n    page.navigateTo();\n    expect(page.getParagraphText()).toEqual('app works!');\n  });\n});\n"
  },
  {
    "path": "e2e/app.po.ts",
    "content": "import { browser, element, by } from 'protractor';\n\nexport class NgADFPage {\n  navigateTo() {\n    return browser.get('/');\n  }\n\n  getParagraphText() {\n    return element(by.css('app-root h1')).getText();\n  }\n}\n"
  },
  {
    "path": "e2e/tsconfig.e2e.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/e2e\",\n    \"module\": \"commonjs\",\n    \"target\": \"es5\",\n    \"types\":[\n      \"jasmine\",\n      \"node\"\n    ]\n  }\n}\n"
  },
  {
    "path": "karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/0.13/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular-devkit/build-angular'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular-devkit/build-angular/plugins/karma')\n    ],\n    client:{\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    files: [\n      \n    ],\n    preprocessors: {\n      \n    },\n    mime: {\n      'text/x-typescript': ['ts','tsx']\n    },\n    coverageIstanbulReporter: {\n      dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],\n      fixWebpackSourcePaths: true\n    },\n    \n    reporters: config.angularCli && config.angularCli.codeCoverage\n              ? ['progress', 'coverage-istanbul']\n              : ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    singleRun: false\n  });\n};\n"
  },
  {
    "path": "ngx-dynamic-dashboard-framework.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"WEB_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\" inherit-compiler-output=\"true\">\n    <exclude-output />\n    <content url=\"file://$MODULE_DIR$\">\n      <excludeFolder url=\"file://$MODULE_DIR$/dist\" />\n      <excludeFolder url=\"file://$MODULE_DIR$/tmp\" />\n    </content>\n    <orderEntry type=\"inheritedJdk\" />\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"ng-dadf\",\n  \"version\": \"0.0.0\",\n  \"license\": \"MIT\",\n  \"ngPackage\": {\n    \"lib\": {\n      \"entryFile\": \"public_api.ts\"\n    }\n  },\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"test\": \"ng test\",\n    \"lint\": \"ng lint\",\n    \"e2e\": \"ng e2e\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/animations\": \"7.2.3\",\n    \"@angular/cdk\": \"^7.3.1\",\n    \"@angular/common\": \"7.2.3\",\n    \"@angular/compiler\": \"^7.2.3\",\n    \"@angular/core\": \"^7.2.3\",\n    \"@angular/forms\": \"7.2.3\",\n    \"@angular/http\": \"7.2.3\",\n    \"@angular/material\": \"^7.3.1\",\n    \"@angular/platform-browser\": \"7.2.3\",\n    \"@angular/platform-browser-dynamic\": \"7.2.3\",\n    \"@angular/router\": \"7.2.3\",\n    \"@swimlane/ngx-charts\": \"10.0.0\",\n    \"core-js\": \"^2.5.7\",\n    \"d3\": \"^5.7.0\",\n    \"d3-shape\": \"^1.2.2\",\n    \"jquery\": \"^3.3.1\",\n    \"material-design-icons\": \"^3.0.1\",\n    \"ng2-cookies\": \"1.0.12\",\n    \"ng2-dnd\": \"^5.0.2\",\n    \"npm\": \"^6.4.1\",\n    \"reflect-metadata\": \"0.1.12\",\n    \"rxjs\": \"^6.4.0\",\n    \"semantic-ui\": \"^2.4.2\",\n    \"socket.io-client\": \"^2.1.1\",\n    \"sockjs-client\": \"^1.3.0\",\n    \"stompjs\": \"^2.3.3\",\n    \"tslib\": \"^1.9.0\",\n    \"zone.js\": \"^0.8.29\"\n  },\n  \"devDependencies\": {\n    \"@angular-devkit/build-angular\": \"^0.13.0\",\n    \"@angular/cli\": \"^7.3.0\",\n    \"@angular/compiler-cli\": \"^7.2.3\",\n    \"@types/jasmine\": \"2.8.9\",\n    \"@types/node\": \"~10.12.2\",\n    \"codelyzer\": \"~4.5.0\",\n    \"jasmine-core\": \"~3.3.0\",\n    \"jasmine-spec-reporter\": \"~4.2.1\",\n    \"karma\": \"^3.1.1\",\n    \"karma-chrome-launcher\": \"~2.2.0\",\n    \"karma-cli\": \"~1.0.1\",\n    \"karma-coverage-istanbul-reporter\": \"^2.0.4\",\n    \"karma-jasmine\": \"~1.1.0\",\n    \"karma-jasmine-html-reporter\": \"^1.4.0\",\n    \"protractor\": \"^5.4.1\",\n    \"ts-node\": \"~7.0.1\",\n    \"tslint\": \"^5.11.0\",\n    \"typescript\": \"^3.2.4\"\n  }\n}\n"
  },
  {
    "path": "protractor.conf.js",
    "content": "// Protractor configuration file, see link for more information\n// https://github.com/angular/protractor/blob/master/lib/config.ts\n\nconst { SpecReporter } = require('jasmine-spec-reporter');\n\nexports.config = {\n  allScriptsTimeout: 11000,\n  specs: [\n    './e2e/**/*.e2e-spec.ts'\n  ],\n  capabilities: {\n    'browserName': 'chrome'\n  },\n  directConnect: true,\n  baseUrl: 'http://localhost:4200/',\n  framework: 'jasmine',\n  jasmineNodeOpts: {\n    showColors: true,\n    defaultTimeoutInterval: 30000,\n    print: function() {}\n  },\n  beforeLaunch: function() {\n    require('ts-node').register({\n      project: 'e2e/tsconfig.e2e.json'\n    });\n  },\n  onPrepare() {\n    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));\n  }\n};\n"
  },
  {
    "path": "semantic.json",
    "content": "{\n  \"base\": \"semantic/\",\n  \"paths\": {\n    \"source\": {\n      \"config\": \"src/theme.config\",\n      \"definitions\": \"src/definitions/\",\n      \"site\": \"src/site/\",\n      \"themes\": \"src/themes/\"\n    },\n    \"output\": {\n      \"packaged\": \"dist/\",\n      \"uncompressed\": \"dist/components/\",\n      \"compressed\": \"dist/components/\",\n      \"themes\": \"dist/themes/\"\n    },\n    \"clean\": \"dist/\"\n  },\n  \"permission\": false,\n  \"autoInstall\": true,\n  \"rtl\": false,\n  \"version\": \"2.4.2\"\n}"
  },
  {
    "path": "src/app/about/about-component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    AfterViewInit, Component, Output, EventEmitter, Input\n} from '@angular/core';\n\nimport {environment} from '../../environments/environment';\nimport {AboutService} from \"./service\";\n\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-about-modal',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css']\n\n})\nexport class AboutComponent implements AfterViewInit {\n\n    modalHeader = 'About';\n    apiVersion: string;\n\n    messageModal: any;\n    env: any;\n\n    constructor(private _aboutService: AboutService) {\n\n        this.env = environment;\n    }\n\n\n    ngAfterViewInit() {\n\n        this.getVersion();\n\n    }\n\n    getVersion() {\n\n        this._aboutService.getAPIVersion().subscribe(data => {\n\n            this.apiVersion = data['version'];\n\n        });\n\n    }\n\n\n}\n"
  },
  {
    "path": "src/app/about/about.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {AboutComponent} from './about-component';\nimport {AboutService} from \"./service\";\n\n@NgModule({\n    imports: [\n        CommonModule\n    ],\n    declarations: [AboutComponent],\n    exports: [AboutComponent],\n    providers: [AboutService]\n})\nexport class AboutModule {\n}\n"
  },
  {
    "path": "src/app/about/model.ts",
    "content": "/**\n * Created by jayhamilton on 1/31/17.\n */\nexport const boardLayouts = [\n\n    {\n        id: 0,\n        boardInstanceId: 0,\n        title: 'one-narrow',\n        checked: false,\n        structure: '8',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'eight wide',\n\n                }]\n        }]\n    },\n    {\n        id: 1,\n        boardInstanceId: 1,\n        title: 'single',\n        checked: false,\n        structure: '14',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'fourteen wide',\n\n                }]\n        }]\n    },\n    {\n        id: 2,\n        boardId: 2,\n        title: 'narrow-right',\n        checked: false,\n        structure: '10-6',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'ten wide',\n\n                },\n                {\n                    styleClass: 'six wide',\n\n                }]\n        }]\n    },\n    {\n        id: 3,\n        boardInstanceId: 3,\n        title: 'wide-center',\n        checked: false,\n        structure: '4-8-4',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'four wide',\n\n                },\n                {\n                    styleClass: 'eight wide',\n\n                },\n                {\n                    styleClass: 'four wide',\n\n                }]\n        }]\n    },\n    {\n        id: 4,\n        boardInstanceId: 4,\n        title: 'narrow-left',\n        checked: false,\n        structure: '4-12',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'four wide',\n\n                },\n                {\n                    styleClass: 'twelve wide',\n\n                }]\n        }]\n    },\n    {\n        id: 5,\n        boardInstanceId: 5,\n        title: 'two-even',\n        checked: true,\n        structure: '6-6',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'six wide',\n\n                },\n                {\n                    styleClass: 'six wide',\n\n                }]\n        }]\n    },\n    {\n        id: 6,\n        boardInstanceId: 6,\n        title: 'three-even',\n        checked: false,\n        structure: '5-5-5',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'five wide',\n\n                },\n                {\n                    styleClass: 'five wide',\n\n                },\n                {\n                    styleClass: 'five wide',\n\n                }\n            ]\n        }]\n    },\n    {\n        id: 7,\n        boardInstanceId: 7,\n        title: 'wide-top',\n        checked: false,\n        structure: '16/8-8',\n        rows: [\n            {\n                columns: [\n                    {\n                        styleClass: 'sixteen wide'\n                    }\n                ]\n            },\n            {\n                columns: [\n                    {\n                        styleClass: 'eight wide'\n                    },\n                    {\n                        styleClass: 'eight wide'\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        id: 8,\n        boardInstanceId: 8,\n        title: 'ngadmin',\n        checked: false,\n        structure: '4-4-4-4/8-4-4',\n        rows: [\n            {\n                columns: [\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    }\n                ]\n            },\n            {\n                columns: [\n                    {\n                        styleClass: 'eight wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        id: 9,\n        boardInstanceId: 9,\n        title: 'google-layout',\n        checked: false,\n        structure: '3-6-3',\n        rows: [\n            {\n                columns: [\n                    {\n                        styleClass: 'three wide'\n                    },\n                    {\n                        styleClass: 'six wide'\n                    },\n                    {\n                        styleClass: 'three wide'\n                    }\n                ]\n            }\n        ]\n    }\n\n];\n"
  },
  {
    "path": "src/app/about/service.ts",
    "content": "import {Injectable} from \"@angular/core\";\nimport {environment} from \"../../environments/environment\";\nimport {HttpClient} from \"@angular/common/http\";\nimport {RuntimeService} from \"../services/runtime.service\";\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class AboutService {\n\n    env: any;\n\n    constructor(private _http: HttpClient) {\n        this.env = environment;\n    }\n\n\n    getAPIVersion() {\n\n        let url: string;\n\n        if (this.env.production == true) {\n\n            url = '/version';\n\n        } else {\n\n            url = '/assets/api/version-model.json';\n\n        }\n\n        return this._http.get(url)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n}"
  },
  {
    "path": "src/app/about/styles.css",
    "content": "\nul{\n    text-align: center;\n}\nh2, h3, h4{\n    color:white !important;\n    font-weight: normal !important;\n}\n"
  },
  {
    "path": "src/app/about/view.html",
    "content": "<br>\n\n<div style=\"text-align: center\">\n    <h2>{{modalHeader}}</h2>\n</div>\n\n<hr>\n\n<br>\n<br>\n\n<div style=\"text-align: center\">\n    <h4>{{env.productName}}</h4>\n</div>\n\n\n<div style=\"text-align: center\">\n    <h4>Version {{env.productVersion}}</h4>\n</div>\n\n<br>\n<br>\n\n<div style=\"text-align: center\">\n    <h4>API Version</h4>\n</div>\n\n<div style=\"text-align: center\">\n    <h4>{{apiVersion}}</h4>\n</div>\n\n\n\n\n\n      "
  },
  {
    "path": "src/app/add-gadget/add-gadget-component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    ViewChild, ElementRef, AfterViewInit, Component, Output, EventEmitter\n} from '@angular/core';\n\nimport {\n    style, trigger, animate, transition\n} from '@angular/animations';\n\nimport {AddGadgetService} from './service';\nimport {Facet} from '../facet/facet-model';\nimport {FacetTagProcessor} from '../facet/facet-tag-processor';\n\ndeclare var jQuery: any;\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-add-gadget-modal',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css'],\n    animations: [\n        trigger(\n            'showHideAnimation',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(750, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(750, style({opacity: 0}))\n                ])\n            ])\n    ]\n\n})\nexport class AddGadgetComponent implements AfterViewInit {\n\n    @Output() addGadgetEvent: EventEmitter<any> = new EventEmitter();\n\n    gadgetObjectList: any[] = [];\n    gadgetObjectTitleList: string[] = [];\n    placeHolderText = 'Begin typing gadget name';\n    layoutColumnOneWidth = 'six';\n    layoutColumnTwoWidth = 'ten';\n    listHeader= 'Gadgets';\n    facetTags: Array<Facet>;\n\n    color = 'white';\n\n    typeAheadIsInMenu = false;\n\n    modalicon: string;\n    modalheader: string;\n    modalmessage: string;\n\n    @ViewChild('messagemodal_tag') messagemodalRef: ElementRef;\n\n    messageModal: any;\n\n    constructor(private _addGadgetService: AddGadgetService) {\n\n        this.getObjectList();\n    }\n\n    actionHandler(actionItem, actionName) {\n        this.addGadgetEvent.emit(actionItem);\n        this.hideMessageModal();\n\n    }\n\n\n    showMessageModal(icon: string, header: string, message: string) {\n        this.modalicon = icon;\n        this.modalheader = header;\n        this.modalmessage = message;\n        this.messageModal.modal('show');\n\n    }\n\n    showComponentLibraryModal(header: string) {\n\n        this.modalheader = header;\n        this.messageModal.modal('show');\n    }\n\n    hideMessageModal() {\n        this.modalicon = '';\n        this.modalheader = '';\n        this.modalmessage = '';\n        this.messageModal.modal('hide');\n    }\n\n    ngAfterViewInit() {\n        this.messageModal = jQuery(this.messagemodalRef.nativeElement);\n    }\n\n    getObjectList() {\n\n        this._addGadgetService.getGadgetLibrary().subscribe(data => {\n            this.gadgetObjectList.length = 0;\n            const me = this;\n            data.library.forEach(function (item) {\n\n                    me.gadgetObjectList.push(item);\n                    me.gadgetObjectTitleList.push(item.name);\n            });\n            const facetTagProcess = new FacetTagProcessor(this.gadgetObjectList);\n            this.facetTags = facetTagProcess.getFacetTags();\n        });\n\n    }\n}\n"
  },
  {
    "path": "src/app/add-gadget/add-gadget.module.ts",
    "content": "import {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {AddGadgetComponent} from './add-gadget-component';\nimport {AddGadgetService} from './service';\nimport {HttpClientModule} from '@angular/common/http';\nimport {DataListModule} from '../datalist/data-list.module';\nimport {MatButtonModule} from '@angular/material';\n\n@NgModule({\n    imports: [\n        CommonModule,\n        DataListModule,\n        HttpClientModule,\n        MatButtonModule,\n    ],\n    declarations: [\n        AddGadgetComponent\n    ],\n    providers: [\n        AddGadgetService\n    ],\n    exports: [\n        AddGadgetComponent\n    ]\n})\nexport class AddGadgetModule {\n}\n\n"
  },
  {
    "path": "src/app/add-gadget/gadget-factory.ts",
    "content": "import {CPUGadgetComponent} from '../gadgets/cpu/cpu-gadget.component';\nimport {MemoryGadgetComponent} from '../gadgets/memory/memory-gadget.component';\nimport {PropertyListGadgetComponent} from '../gadgets/property-list/property-list-gadget.component';\nimport {DiskGadgetComponent} from '../gadgets/disk/disk-gadget.component';\nimport {ServiceListGadgetComponent} from '../gadgets/service-list/service-list-gadget.component';\nimport {StatisticGadgetComponent} from '../gadgets/statistic/statistic-gadget.component';\nimport {TrendGadgetComponent} from '../gadgets/trend/trend-gadget.component';\nimport {NewsGadgetComponent} from '../gadgets/news/news-gadget.component';\nimport {JobAnalysisGadgetComponent} from '../gadgets/job-analysis/job-analysis-gadget.component';\nimport {TrendLineGadgetComponent} from '../gadgets/trend-line/trend-line-gadget.component';\nimport {EdgeServiceListGadgetComponent} from '../gadgets/edge-service-list/edge-service-list-gadget.component';\nimport {CPUMGadgetComponent} from '../gadgets/cpum/cpum-gadget.component';\nimport {PortConnectionGadgetComponent} from '../gadgets/port-connection/port-connection-gadget.component';\nimport {StorageObjectListComponent} from '../gadgets/storage-object-list/storage-object-list.component';\nimport {DonutGadgetComponent} from '../gadgets/donut/donut-gadget.component';\nimport {TodoGadgetComponent} from '../gadgets/todo/todo-gadget.component';\nimport {BubbleGadgetComponent} from \"../gadgets/bubble/bubble-gadget.component\";\nimport {BarChartGadgetComponent} from \"../gadgets/barchart/barchart-gadget.component\";\nimport {PieChartGadgetComponent} from \"../gadgets/piechart/piechart-gadget.component\";\n\n/**\n * Created by jayhamilton on 6/30/17.\n */\n\nexport class GadgetFactory {\n\n\n    /**\n     * todo - return new instances  instead of the same instance. This requires the creation of new configuration options.\n     * @param gadgetType\n     * @returns {any}\n     */\n\n    static getComponentType(gadgetType): any {\n\n        switch (gadgetType) {\n\n            case 'DonutGadgetComponent':\n                return DonutGadgetComponent;\n            case 'CPUGadgetComponent':\n                return CPUGadgetComponent;\n            case 'MemoryGadgetComponent':\n                return MemoryGadgetComponent;\n            case 'PropertyListGadgetComponent':\n                return PropertyListGadgetComponent;\n            case 'DiskGadgetComponent':\n                return DiskGadgetComponent;\n            case 'ServiceListGadgetComponent':\n                return ServiceListGadgetComponent;\n            case 'StatisticGadgetComponent':\n                return StatisticGadgetComponent;\n            case 'TrendGadgetComponent':\n                return TrendGadgetComponent;\n            case 'NewsGadgetComponent':\n                return NewsGadgetComponent;\n            case'JobAnalysisGadgetComponent':\n                return JobAnalysisGadgetComponent;\n            case'TrendLineGadgetComponent':\n                return TrendLineGadgetComponent;\n            case'EdgeServiceListGadgetComponent':\n                return EdgeServiceListGadgetComponent;\n            case 'CPUMGadgetComponent':\n                return CPUMGadgetComponent;\n            case 'PortConnectionGadgetComponent':\n                return PortConnectionGadgetComponent;\n            case 'StorageObjectListComponent':\n                return StorageObjectListComponent;\n            case 'TodoGadgetComponent': // todo gadget\n                return TodoGadgetComponent;\n            case 'BubbleGadgetComponent': // todo gadget\n                return BubbleGadgetComponent;\n            case 'BarChartGadgetComponent': // todo gadget\n                return BarChartGadgetComponent;\n            case 'PieChartGadgetComponent': // todo gadget\n                return PieChartGadgetComponent;\n            default:\n                return null;// todo add default gadget that would be displayed. Useful for troubleshooting new gadget dev\n\n        }\n    }\n}\n"
  },
  {
    "path": "src/app/add-gadget/gadgetLibraryResponse.ts",
    "content": "interface GadgetLibraryResponse {\n    library: any[];\n}\n"
  },
  {
    "path": "src/app/add-gadget/service.ts",
    "content": "/**\n * Created by jayhamilton on 2/7/17.\n */\nimport {Injectable} from '@angular/core';\nimport {HttpClient} from '@angular/common/http';\nimport {environment} from '../../environments/environment'\n\n@Injectable()\nexport class AddGadgetService {\n\n    env: any;\n\n    constructor(private _http: HttpClient) {\n        this.env = environment;\n    }\n\n    getGadgetLibrary() {\n        let gadgetLibraryJson = '';\n\n        if (this.env.production == true) {\n            gadgetLibraryJson = 'gadget-library-model-prod.json';\n\n        } else {\n            gadgetLibraryJson = 'gadget-library-model.json';\n        }\n        return this._http.get<GadgetLibraryResponse>('/assets/api/' + gadgetLibraryJson);\n    }\n\n}\n"
  },
  {
    "path": "src/app/add-gadget/styles.css",
    "content": ".modal{\n    background-color:#f7f7f7;\n\n}\n"
  },
  {
    "path": "src/app/add-gadget/view.html",
    "content": "<div class=\"ui long modal\" #messagemodal_tag>\n    <div class=\"header\">\n        <h2>{{modalheader}}</h2>\n    </div>\n\n    <app-data-list\n\n            [objectList]=\"gadgetObjectList\"\n            [objectTitleList]=\"gadgetObjectTitleList\"\n            [placeHolderText]=\"placeHolderText\"\n            [typeAheadIsInMenu]=\"typeAheadIsInMenu\"\n            [layoutColumnOneWidth]=\"layoutColumnOneWidth\"\n            [layoutColumnTwoWidth]=\"layoutColumnTwoWidth\"\n            [listHeader]=\"listHeader\"\n            [facetTags]=\"facetTags\">\n\n            <ng-template  let-item=\"$implicit\">\n\n                <div [@showHideAnimation] class=\"ui segment\" style=\"background-color:white;\">\n                    <div class=\"ui large middle aligned divided list\">\n                        <div class=\"item\">\n                            <div class=\"right floated content\">\n                                <!-- todo : if there are more than one action display a button with\n                                vertical ellipse and implement onHover to show all action buttons\n                                -->\n                                <a *ngIf=\"item.actions.length == 1\"\n                                   mat-raised-button\n                                   routerLink=\".\"\n                                   (click)=\"actionHandler(item, item.actions[0].name)\" color=\"primary\">\n                                    {{item.actions[0].name}}\n                                </a>\n                            </div>\n                            <img class=\"ui image\" src=\"{{item.icon}}\">\n                            <div class=\"content\">\n                                <div class=\"header\">{{item.name}}</div>\n                                {{item.description}}\n                            </div>\n                        </div>\n                    </div>\n                    <div class=\"ui bottom attached\">\n                        <button *ngFor=\"let tag of item.tags\" class=\"ui basic gray compact button\">{{tag.name}}\n                        </button>\n                    </div>\n                </div>\n\n            </ng-template>\n\n        </app-data-list>\n\n    <div class=\"actions\">\n        <div class=\"ui approve button\">Close</div>\n    </div>\n</div>\n      "
  },
  {
    "path": "src/app/api-token/api-token.service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {HttpClient, HttpHeaders} from '@angular/common/http';\n\n@Injectable()\nexport class APITokenService {\n\n    private apiToken: string;\n    private credentials = {url: '', user: '', password: ''};\n\n    constructor(private _http: HttpClient) {\n    }\n\n    public getAPITokenForCredentials(_credentials: any) {\n        let headers = new HttpHeaders();\n\n        this.credentials = _credentials;\n\n        headers = headers.append('Content-Type', 'application/json');\n        headers = headers.append('Authorization', 'Basic ' + B64encode(this.credentials.user + ':' + this.credentials.password));\n\n        return this._http.post(this.credentials.url, '', {headers: headers});\n\n    }\n\n    public setAPIToken(apiToken: string) {\n        this.apiToken = apiToken;\n    }\n\n    public getAPIToken() {\n        return this.apiToken;\n    }\n}\n\nfunction B64encode(data: string) {\n\n    var c1, c2, c3;\n    var Base64 = {\n        _keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', encode: function (e) {\n            var t = '';\n            var n, r, i, s, o, u, a;\n            var f = 0;\n            e = Base64._utf8_encode(e);\n            while (f < e.length) {\n                n = e.charCodeAt(f++);\n                r = e.charCodeAt(f++);\n                i = e.charCodeAt(f++);\n                s = n >> 2;\n                o = (n & 3) << 4 | r >> 4;\n                u = (r & 15) << 2 | i >> 6;\n                a = i & 63;\n                if (isNaN(r)) {\n                    u = a = 64\n                } else if (isNaN(i)) {\n                    a = 64\n                }\n                t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)\n            }\n            return t\n        }, decode: function (e) {\n            var t = '';\n            var n, r, i;\n            var s, o, u, a;\n            var f = 0;\n            e = e.replace(/[^A-Za-z0-9\\+\\/\\=]/g, '');\n            while (f < e.length) {\n                s = this._keyStr.indexOf(e.charAt(f++));\n                o = this._keyStr.indexOf(e.charAt(f++));\n                u = this._keyStr.indexOf(e.charAt(f++));\n                a = this._keyStr.indexOf(e.charAt(f++));\n                n = s << 2 | o >> 4;\n                r = (o & 15) << 4 | u >> 2;\n                i = (u & 3) << 6 | a;\n                t = t + String.fromCharCode(n);\n                if (u != 64) {\n                    t = t + String.fromCharCode(r);\n                }\n                if (a != 64) {\n                    t = t + String.fromCharCode(i);\n                }\n            }\n            t = Base64._utf8_decode(t);\n            return t;\n        }, _utf8_encode: function (e) {\n            e = e.replace(/\\r\\n/g, '\\n');\n            var t = '';\n            for (var n = 0; n < e.length; n++) {\n                var r = e.charCodeAt(n);\n                if (r < 128) {\n                    t += String.fromCharCode(r);\n                } else if (r > 127 && r < 2048) {\n                    t += String.fromCharCode(r >> 6 | 192);\n                    t += String.fromCharCode(r & 63 | 128);\n                } else {\n                    t += String.fromCharCode(r >> 12 | 224);\n                    t += String.fromCharCode(r >> 6 & 63 | 128);\n                    t += String.fromCharCode(r & 63 | 128);\n                }\n            }\n            return t;\n        }, _utf8_decode: function (e) {\n            var t = '';\n            var n = 0;\n            var r = c1 = c2 = 0;\n            while (n < e.length) {\n                r = e.charCodeAt(n);\n                if (r < 128) {\n                    t += String.fromCharCode(r);\n                    n++\n                } else if (r > 191 && r < 224) {\n                    c2 = e.charCodeAt(n + 1);\n                    t += String.fromCharCode((r & 31) << 6 | c2 & 63);\n                    n += 2\n                } else {\n                    c2 = e.charCodeAt(n + 1);\n                    c3 = e.charCodeAt(n + 2);\n                    t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);\n                    n += 3\n                }\n            }\n            return t;\n        }\n    }\n\n    return Base64.encode(data);\n\n}"
  },
  {
    "path": "src/app/app.component.css",
    "content": ""
  },
  {
    "path": "src/app/app.component.html",
    "content": "<!--\nThe grid is primarily controlled by MenuService Events. You can change the behavior by\nchanging the MenuComponent and have it call methods within the Grid component via Output Events within the Menu component or by using the @ViewChild approach.\n\nIn the current code, the MenuService is shared by the GridComponent and MenuComponent. The MenuComponent relays events from the various components that make up the MenuComponent. The GridComponent listens for those events via an Observable. The GridComponent will also raise/emit an event that will be picked up by the MenuComponent via the MenuService through an Observable as well.\n-->\n<app-menu-component></app-menu-component>\n<router-outlet></router-outlet>\n"
  },
  {
    "path": "src/app/app.component.spec.ts",
    "content": "import { TestBed, async } from '@angular/core/testing';\nimport 'rxjs/Rx';\n\nimport { AppComponent } from './app.component';\nimport {RoutingModule} from './routing.module';\n\n\ndescribe('AppComponent', () => {\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      declarations: [\n        AppComponent\n      ],\n        imports: [\n            RoutingModule\n        ]\n    }).compileComponents();\n  }));\n\n  it('should create the app', async(() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app).toBeTruthy();\n  }));\n\n  /*\n  it(`should have as title 'app works!'`, async(() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app.title).toEqual('app works!');\n  }));\n\n  it('should render title in a h1 tag', async(() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    fixture.detectChanges();\n    const compiled = fixture.debugElement.nativeElement;\n    expect(compiled.querySelector('h1').textContent).toContain('app works!');\n  }));\n\n  */\n});\n"
  },
  {
    "path": "src/app/app.component.ts",
    "content": "import { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html',\n  styleUrls: ['./app.component.css']\n})\nexport class AppComponent {\n  title = 'app works!';\n}\n"
  },
  {
    "path": "src/app/app.module.ts",
    "content": "import {BrowserModule} from '@angular/platform-browser';\nimport {NgModule} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {AppComponent} from './app.component';\nimport {RoutingModule} from './routing.module';\nimport {BrowserAnimationsModule} from '@angular/platform-browser/animations';\nimport {HttpClientJsonpModule, HttpClientModule} from '@angular/common/http';\nimport {DetailModule} from './detail/detail.module';\nimport {MenuModule} from './menu/menu.module';\nimport {BoardModule} from './board/board.module';\n\n@NgModule({\n    imports: [\n        BrowserModule,\n        BrowserAnimationsModule,\n        RoutingModule,\n        FormsModule,\n        HttpClientModule,\n        BoardModule,\n        MenuModule,\n        DetailModule,\n        HttpClientJsonpModule\n    ],\n    declarations: [\n        AppComponent,\n    ],\n\n    bootstrap: [AppComponent]\n})\nexport class AppModule {\n}\n"
  },
  {
    "path": "src/app/board/board.component.ts",
    "content": "import { Component} from '@angular/core';\n/**a\n * Board component\n *\n */\n@Component({\n    moduleId: module.id,\n    templateUrl: './view.html'\n\n})\nexport class BoardComponent {\n\n}\n"
  },
  {
    "path": "src/app/board/board.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {GridModule} from '../grid/grid.module';\nimport {BoardComponent} from './board.component';\nimport {CPUMGadgetComponent} from '../gadgets/cpum/cpum-gadget.component';\nimport {EdgeServiceListGadgetComponent} from '../gadgets/edge-service-list/edge-service-list-gadget.component';\nimport {TrendLineGadgetComponent} from '../gadgets/trend-line/trend-line-gadget.component';\nimport {JobAnalysisGadgetComponent} from '../gadgets/job-analysis/job-analysis-gadget.component';\nimport {NewsGadgetComponent} from '../gadgets/news/news-gadget.component';\nimport {TrendGadgetComponent} from '../gadgets/trend/trend-gadget.component';\nimport {StatisticGadgetComponent} from '../gadgets/statistic/statistic-gadget.component';\nimport {DiskGadgetComponent} from '../gadgets/disk/disk-gadget.component';\nimport {PropertyListGadgetComponent} from '../gadgets/property-list/property-list-gadget.component';\nimport {ServiceListGadgetComponent} from '../gadgets/service-list/service-list-gadget.component';\nimport {CPUGadgetComponent} from '../gadgets/cpu/cpu-gadget.component';\nimport {MemoryGadgetComponent} from '../gadgets/memory/memory-gadget.component';\nimport {PortConnectionGadgetComponent} from '../gadgets/port-connection/port-connection-gadget.component';\nimport {StorageObjectListComponent} from '../gadgets/storage-object-list/storage-object-list.component';\nimport {DonutGadgetComponent} from '../gadgets/donut/donut-gadget.component';\nimport {TodoGadgetComponent} from '../gadgets/todo/todo-gadget.component';  // todo gadget\nimport {BubbleGadgetComponent} from \"../gadgets/bubble/bubble-gadget.component\";\nimport {BarChartGadgetComponent} from \"../gadgets/barchart/barchart-gadget.component\";\nimport {PieChartGadgetComponent} from \"../gadgets/piechart/piechart-gadget.component\";\n\n@NgModule({\n    imports: [\n        CommonModule,\n        GridModule.withComponents([\n            MemoryGadgetComponent,\n            CPUGadgetComponent,\n            ServiceListGadgetComponent,\n            PropertyListGadgetComponent,\n            DiskGadgetComponent,\n            StatisticGadgetComponent,\n            TrendGadgetComponent,\n            NewsGadgetComponent,\n            JobAnalysisGadgetComponent,\n            TrendLineGadgetComponent,\n            EdgeServiceListGadgetComponent,\n            CPUMGadgetComponent,\n            PortConnectionGadgetComponent,\n            StorageObjectListComponent,\n            DonutGadgetComponent,\n            TodoGadgetComponent  // todo gadget\n            , BubbleGadgetComponent,\n            BarChartGadgetComponent,\n            PieChartGadgetComponent\n\n        ]),\n    ],\n    providers: [],\n    declarations: [\n        BoardComponent\n    ]\n})\nexport class BoardModule {\n}\n"
  },
  {
    "path": "src/app/board/view.html",
    "content": "<!--\n\nThe grid is primarily controlled by MenuService Events. You can change the behavior by\nchanging the MenuComponent and have it call methods within the Grid component via Output Events within the Menu component or by using the @ViewChild approach.\n\nIn the current code, the MenuService is shared by the GridComponent and MenuComponent. The MenuComponent relays events from the various components that make up the MenuComponent. The GridComponent listens for those events via an Observable. The GridComponent will also raise/emit an event that will be picked up by the MenuComponent via the MenuService through an Observable as well.\n\n-->\n<app-grid-component></app-grid-component>\n\n"
  },
  {
    "path": "src/app/configuration/configuration-component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    ViewChild, ElementRef, AfterViewInit, Component, Output, EventEmitter, Input\n} from '@angular/core';\nimport {\n     style, state, trigger, animate, transition\n} from '@angular/animations';\n\nimport {tabsModel} from './tabs.model';\nimport {environment} from '../../environments/environment'\n\n\ndeclare var jQuery: any;\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-configuration-modal',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css'],\n    animations: [\n\n        trigger('contentSwitch', [\n            state('inactive', style({\n                opacity: 0\n            })),\n            state('active', style({\n                opacity: 1\n            })),\n            transition('inactive => active', animate('750ms ease-in')),\n            transition('active => inactive', animate('750ms ease-out'))\n        ])\n    ]\n\n\n})\nexport class ConfigurationComponent implements AfterViewInit {\n\n    @Output() dashboardCreateEvent: EventEmitter<any> = new EventEmitter();\n    @Output() dashboardEditEvent: EventEmitter<any> = new EventEmitter();\n    @Output() dashboardDeleteEvent: EventEmitter<any> = new EventEmitter();\n    @Input() dashboardList: any [];\n\n\n    newDashboardItem = '';\n\n\n    modalicon: string;\n    modalheader: string;\n    modalconfig: string;\n    env:any;\n\n    @ViewChild('boardconfigmodal_tag') boardconfigmodalaRef: ElementRef;\n    configModal: any;\n    currentTab: string;\n    tabsModel: any[];\n\n    constructor() {\n\n        Object.assign(this, {tabsModel});\n        this.setCurrentTab(0);\n        this.env = environment;\n\n    }\n\n\n    showConfigurationModal(header: string) {\n        this.modalheader = header;\n        this.configModal.modal('show');\n    }\n\n    hideMessageModal() {\n        this.modalicon = '';\n        this.modalheader = '';\n        this.modalconfig = '';\n        this.configModal.modal('hide');\n    }\n\n    createBoard(name: string) {\n        if (name !==  '') {\n            this.dashboardCreateEvent.emit(name);\n            this.newDashboardItem = '';\n        }\n        console.log(\"Creating new board event from configuration component: \" + name);\n    }\n\n    editBoard(name: string) {\n        this.dashboardEditEvent.emit(name);\n    }\n\n    deleteBoard(name: string) {\n        this.dashboardDeleteEvent.emit(name);\n    }\n\n\n    ngAfterViewInit() {\n        this.configModal = jQuery(this.boardconfigmodalaRef.nativeElement);\n        this.configModal.modal('hide');\n    }\n\n    setCurrentTab(tab_index) {\n        this.currentTab = this.tabsModel[tab_index].displayName;\n    }\n\n}\n"
  },
  {
    "path": "src/app/configuration/configuration.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {EndpointConfigurationTabComponent} from './tab-endpoint/endpoint-configuration-tab.component';\nimport {EndPointDetailComponent} from './tab-endpoint/endpointDetail.component';\nimport {EndPointService} from './tab-endpoint/endpoint.service';\nimport {BoardsConfigurationTabComponent} from './tab-boards/boards-configuration-tab.component';\nimport {DndModule} from 'ng2-dnd';\nimport {\n    MatButtonModule,\n    MatCheckboxModule,\n    MatIconModule,\n    MatInputModule,\n    MatOptionModule,\n    MatSelectModule,\n    MatSlideToggleModule,\n    MatChipsModule\n} from '@angular/material';\nimport {FormsModule, ReactiveFormsModule} from '@angular/forms';\nimport {AIConfigurationTabComponent} from './tab-artificial-intelligence/ai-configuration-tab.component';\nimport {OptionsConfigurationTabComponent} from \"./tab-options/options-configuration-tab.component\";\nimport {ConfigurationComponent} from \"./configuration-component\";\nimport {OptionsService} from \"./tab-options/service\";\n\n@NgModule({\n    imports: [\n        CommonModule,\n        DndModule.forRoot(),\n        MatButtonModule,\n        MatIconModule,\n        MatCheckboxModule,\n        MatInputModule,\n        MatSelectModule,\n        MatOptionModule,\n        FormsModule,\n        ReactiveFormsModule,\n        MatSlideToggleModule,\n        MatChipsModule\n    ],\n    declarations: [\n        BoardsConfigurationTabComponent,\n        EndpointConfigurationTabComponent,\n        EndPointDetailComponent,\n        AIConfigurationTabComponent,\n        OptionsConfigurationTabComponent,\n        ConfigurationComponent\n    ],\n    providers: [\n\n        EndPointService,\n        OptionsService\n    ],\n    exports: [\n        BoardsConfigurationTabComponent,\n        EndpointConfigurationTabComponent,\n        EndPointDetailComponent,\n        OptionsConfigurationTabComponent,\n        ConfigurationComponent\n    ]\n})\nexport class ConfigurationModule {\n}\n"
  },
  {
    "path": "src/app/configuration/styles.css",
    "content": "\n.ui.tabular.menu .active.item {\n    border-top: 3px solid #3f51b5 !important;\n}\n\n.ui.attached.segment {\n    margin: 0;\n    width: 100%;\n}"
  },
  {
    "path": "src/app/configuration/tab-artificial-intelligence/ai-configuration-tab.component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    Component\n} from '@angular/core';\n\nimport {environment} from '../../../environments/environment';\n\n\n@Component({\n    selector: 'app-ai-config-tab',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css']\n})\nexport class AIConfigurationTabComponent {\n\n    token;\n    ibmwatsonuid;\n    ibmwatsonpwd;\n    ibmwatsoncid;\n\n    ai_engines = [\n        {value: 'watson', viewValue: 'Watson'},\n        {value: 'witai', viewValue: 'WitAI'},\n        {value: ' ', viewValue: ' '}\n    ];\n    selectedAIEngineValue: string;\n    env: any;\n\n    constructor() {\n        /**\n         * todo - get this information from a backend store\n         * **/\n\n        this.env = environment;\n\n        if (this.env.experimental) {\n\n            this.token = localStorage.getItem('Wit.aiToken');\n            this.ibmwatsonuid = localStorage.getItem('ibmwatsonuid');\n            this.ibmwatsonpwd = localStorage.getItem('ibmwatsonpwd');\n            this.ibmwatsoncid = localStorage.getItem('ibmwatsoncid');\n            this.selectedAIEngineValue = localStorage.getItem('ai_engine');\n        }\n    }\n\n    selectChange(selectControl) {\n\n        console.log(selectControl.value);\n        this.selectedAIEngineValue = selectControl.value;\n        localStorage.setItem('ai_engine', selectControl.value);\n\n    }\n\n    save() {\n\n        /**\n         * todo - get this information from a backend store\n         * **/\n        if (!environment.production) {\n            localStorage.setItem('Wit.aiToken', this.token);\n            localStorage.setItem('ibmwatsonuid', this.ibmwatsonuid);\n            localStorage.setItem('ibmwatsonpwd', this.ibmwatsonpwd);\n            localStorage.setItem('ibmwatsoncid', this.ibmwatsoncid);\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/app/configuration/tab-artificial-intelligence/styles.css",
    "content": ".ui.menu{\n    margin-bottom: .1em !important;\n}\n\n\n.ui.secondary.pointing.menu .active.item {\n    color:  #3f51b5 !important;\n    font-weight: 500 !important;\n    border-color: #3f51b5 !important;\n    border-width: medium !important;\n    font-family: 'Roboto', sans-serif !important;\n    font-size: 1.4em;\n}\n\n.ui.secondary.pointing.menu .item {\n    color: rgba(0, 0, 0, 0.3) !important;\n    font-weight: 500 !important;\n    font-family: 'Roboto', sans-serif !important;\n    font-size: 1.4em;\n}\n\n.ui.secondary.pointing.menu {\n    border-bottom: none !important;\n}\n\n.ui.tabular.menu .active.item {\n\n    border-top-width: 3px !important;\n    border-top-color: #3f51b5 !important;\n\n}\n\ninput {\n    padding: 5px;\n    font-weight: 300 !important;\n    font-family: 'Roboto', sans-serif !important;\n    font-size: 1.1em;\n    outline: none !important;\n}\n\n#content {\n    background: #3f51b5;\n    width: 120px;\n    margin-left: auto;\n    margin-right: auto;\n    position: relative;\n    top: 50%;\n    transform: translateY(-50%);\n}\n\nlabel {\n    font-family: 'Roboto', sans-serif;\n    font-size: 1.3em !important;\n    color: #4a4d50 !important;\n}\n\nlabel.endpoint {\n    font-size: 1em !important;\n    line-height: 1.5em !important;\n}\n\ntd.detail {\n\n    background-color: white !important;\n\n}\n\n.c-col {\n\n    background-color: #ddebf5 !important;\n    border: none !important;\n    width: 5% !important;\n    color: #788ca0 !important;\n\n}\n\n.ui.table thead th td {\n    color: #788ca0 !important;\n}\n\n\n.ui.table {\n    color: rgba(97, 97, 97, 0.68) !important\n}\n\n.inLine {\n    display: inline-block;\n    padding-left: 4px;\n    padding-right: 4px;\n}\n\n.ui.tabular.menu + .attached:not(.top).segment, .ui.tabular.menu + .attached:not(.top).segment + .attached:not(.top).segment {\n    border-bottom: none !important;\n}\n\n.example-full-width {\n    width: 100%;\n}\n\n.grid-row {\n    display: flex;\n    align-items: center;\n    justify-content: space-around;\n}"
  },
  {
    "path": "src/app/configuration/tab-artificial-intelligence/view.html",
    "content": "<div *ngIf=\"env.boardConfiguration.ai == true\" class=\"ui equal width fields centered grid container\">\n\n    <div class=\"row\">\n        <div class=\"field four wide column\">\n        </div>\n        <div class=\"field eight wide column\">\n            <mat-form-field>\n                <mat-select placeholder=\"Select an AI engine\" (selectionChange)=\"selectChange($event)\" [value]=\"selectedAIEngineValue\">\n                    <mat-option *ngFor=\"let ai_engine of ai_engines\" [value]=\"ai_engine.value\">\n                        {{ ai_engine.viewValue }}\n                    </mat-option>\n                </mat-select>\n            </mat-form-field>\n        </div>\n        <div class=\"field four wide column\">\n        </div>\n    </div>\n\n    <div *ngIf=\"selectedAIEngineValue === '' || selectedAIEngineValue === 'witai'\">\n        <div class=\"row\">\n            <div class=\"field four wide column\">\n            </div>\n            <div class=\"field eight wide column\">\n\n                <h3>Wit.ai Access Token</h3>\n                <mat-form-field class=\"example-full-width\">\n                    <input matInput type=\"password\" placeholder='Enter the access token string from Wit.ai'\n                           [(ngModel)]='token'>\n                </mat-form-field>\n                <a\n                        mat-raised-button\n                        routerLink=\".\"\n                        (click)=\"save()\" color=\"primary\">\n                    Save\n                </a>\n            </div>\n            <div class=\"field four wide column\">\n            </div>\n        </div>\n    </div>\n    <div *ngIf=\"selectedAIEngineValue === 'watson'\">\n        <div class=\"row\">\n            <div class=\"field four wide column\">\n            </div>\n            <div class=\"field eight wide column\">\n\n                <h3>IBM Watson User</h3>\n                <mat-form-field class=\"example-full-width\">\n                    <input matInput type=\"text\" placeholder='Enter the IBM Watson User Id'\n                           [(ngModel)]='ibmwatsonuid'>\n                </mat-form-field>\n                <h3>IBM Watson Password</h3>\n                <mat-form-field class=\"example-full-width\">\n                    <input matInput type=\"password\" placeholder='Enter the IBM Watson Password'\n                           [(ngModel)]='ibmwatsonpwd'>\n                </mat-form-field>\n\n                <h3>IBM Watson Classifier ID</h3>\n                <mat-form-field class=\"example-full-width\">\n                    <input matInput type=\"text\" placeholder='Enter the IBM Watson Classifier Id'\n                           [(ngModel)]='ibmwatsoncid'>\n                </mat-form-field>\n                <a\n                        mat-raised-button\n                        routerLink=\".\"\n                        (click)=\"save()\" color=\"primary\">\n                    Save\n                </a>\n            </div>\n            <div class=\"field four wide column\">\n            </div>\n        </div>\n    </div>\n\n</div>\n\n<div *ngIf=\"env.boardConfiguration.ai == false\">\n    This feature is not ready yet!\n</div>\n\n\n"
  },
  {
    "path": "src/app/configuration/tab-boards/boards-configuration-tab.component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    Component, Output, EventEmitter, Input\n} from '@angular/core';\n\nimport {ConfigurationService} from '../../services/configuration.service';\nimport {environment} from '../../../environments/environment'\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-boards-config-tab',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css']\n\n})\nexport class BoardsConfigurationTabComponent {\n\n    @Output() dashboardCreateEvent: EventEmitter<any> = new EventEmitter();\n    @Output() dashboardEditEvent: EventEmitter<any> = new EventEmitter();\n    @Output() dashboardDeleteEvent: EventEmitter<any> = new EventEmitter();\n    @Input() dashboardList: any [];\n\n\n    newDashboardItem = '';\n    env: any;\n\n    constructor(private _configurationService: ConfigurationService) {\n\n        this.env = environment;\n\n    }\n\n\n    createBoard(name: string) {\n        if (name !== '') {\n            this.dashboardCreateEvent.emit(name);\n            this.newDashboardItem = '';\n        }\n    }\n\n    editBoard(name: string) {\n        this.dashboardEditEvent.emit(name);\n    }\n\n    deleteBoard(name: string) {\n        this.dashboardDeleteEvent.emit(name);\n    }\n\n}\n"
  },
  {
    "path": "src/app/configuration/tab-boards/styles.css",
    "content": "\n\ninput {\n    padding: 5px;\n    font-weight: 300 !important;\n    font-family: 'Roboto', sans-serif !important;\n    font-size: 1.1em;\n    outline: none !important;\n}\n\n\nlabel {\n    font-family: 'Roboto', sans-serif;\n    font-size: 1.3em !important;\n    color: #4a4d50 !important;\n}\n\nlabel.endpoint {\n    font-size: 1em !important;\n    line-height: 1.5em !important;\n}\n\ntd.detail {\n\n    background-color: white !important;\n\n}\n\n.index-column {\n\n    background-color: #ddebf5 !important;\n    border: none !important;\n    width: 5% !important;\n    color: #788ca0 !important;\n\n}\n\n.ui.table thead th td {\n    color: #788ca0 !important;\n}\n\n.ui.table {\n    color: rgba(97, 97, 97, 0.68) !important\n}\n\n.inLine {\n    display: inline-block;\n    padding-left: 4px;\n    padding-right: 4px;\n}\n\n\n.example-full-width {\n    width: 100%;\n}\n\n.grid-row {\n    display: flex;\n    align-items: center;\n    justify-content: space-around;\n}"
  },
  {
    "path": "src/app/configuration/tab-boards/view.html",
    "content": "<table class=\"ui padded table\" dnd-sortable-container [sortableData]=\"dashboardList\">\n    <thead>\n    <th class=\"index-column\">#</th>\n    <th>name</th>\n    <th></th>\n    </thead>\n    <tr class=\"ui basic segment\" *ngFor=\"let board of dashboardList; let i = index\" dnd-sortable\n        [sortableIndex]=\"i\">\n        <td class=\"index-column\">{{i + 1}}</td>\n        <td>{{board}}</td>\n        <td style=\"text-align:right\">\n            <a mat-mini-fab routerLink=\".\" (click)=\"deleteBoard(board)\">\n                <mat-icon>clear</mat-icon>\n            </a>\n        </td>\n    </tr>\n</table>\n\n<div class=\"ui basic segment\">\n\n    <div class=\"grid-row\">\n        <mat-form-field class=\"example-full-width\">\n            <input [(ngModel)]=\"newDashboardItem\" matInput placeholder=\"Enter Dashboard Name\">\n        </mat-form-field>\n\n        <a mat-mini-fab routerLink=\".\" color='primary' (click)=\"createBoard(newDashboardItem)\">\n            <mat-icon>add</mat-icon>\n        </a>\n    </div>\n\n</div>"
  },
  {
    "path": "src/app/configuration/tab-endpoint/endpoint-configuration-tab.component.ts",
    "content": "/**\n * Created by jayhamilton on 5/31/17.\n */\nimport {Component} from '@angular/core';\nimport {EndPoint} from './endpoint.model';\nimport {EndPointService} from './endpoint.service';\nimport {environment} from '../../../environments/environment';\n\n@Component({\n    selector: 'app-endpoint-config-tab',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css']\n\n\n})\nexport class EndpointConfigurationTabComponent {\n\n    env:any;\n\n    endPoints: EndPoint[];\n\n    currentEndPoint: EndPoint = new EndPoint('', '', '', '', '', '',\n        '', '', '',{'tags':[]});\n\n    constructor(private _endPointService: EndPointService) {\n\n        this.env = environment;\n\n        this._endPointService.getEndPoints().subscribe(data => {\n            this.endPoints = data['endPoint'];\n\n            if (this.endPoints && this.endPoints.length) {\n                this.setSelectedEndPoint(this.endPoints[0]);\n            }\n\n        });\n    }\n\n    setSelectedEndPoint(endPoint: EndPoint) {\n        this.currentEndPoint = endPoint;\n    }\n\n    createEndPoint(endPoint: EndPoint) {\n\n        if (!this.endPoints) {\n            this.endPoints = [];\n        }\n\n        this.endPoints.push(endPoint);\n\n        this.persistInMemoryDataToStore();\n\n        this.setSelectedEndPoint(endPoint);\n    }\n\n    updateEndPoint(endPoint: EndPoint) {\n\n        this.deleteEndPoint(endPoint);\n        this.createEndPoint(endPoint);\n\n    }\n\n    deleteEndPoint(endPoint: EndPoint) {\n\n        // find endPoint in memory by name for now (need to use the id) and remove it\n        this.endPoints.forEach(item => {\n\n            if (item.name === endPoint.name) {\n                const index = this.endPoints.indexOf(item);\n                if (index > -1) {\n                    this.endPoints.splice(index, 1);\n                }\n            }\n        });\n\n\n        this.persistInMemoryDataToStore();\n\n        if (this.endPoints && this.endPoints.length === 0) {\n            this.currentEndPoint.name = '';\n            this.currentEndPoint.address = '';\n            this.currentEndPoint.description = '';\n            this.currentEndPoint.credential = '';\n            this.currentEndPoint.credentialType = '';\n            this.currentEndPoint.tokenAPI = '';\n            this.currentEndPoint.tokenAPIProperty = '';\n            this.currentEndPoint.user = '';\n        }else{\n            this.setSelectedEndPoint(this.endPoints[0])\n        }\n    }\n\n    persistInMemoryDataToStore() {\n\n        const endpointModel = {\n            endPoint: this.endPoints\n        };\n        // persist in memory structure\n        this._endPointService.saveEndPoint(endpointModel).subscribe(data => {\n\n            /**\n             * todo - error handling\n             */\n        });\n\n    }\n\n}\n\n\n"
  },
  {
    "path": "src/app/configuration/tab-endpoint/endpoint.help.ts",
    "content": "/**\n * Created by jayhamilton on 5/18/17.\n */\n"
  },
  {
    "path": "src/app/configuration/tab-endpoint/endpoint.model.ts",
    "content": "export interface TAG {\n    name: string;\n}\n\nexport class EndPoint {\n    public id: number;\n    public name: string;\n    public address: string;\n    public user: string;\n    public credentialType: string;\n    public credential: string;\n    public description: string;\n    public tokenAPI: string;\n    public tokenAPIProperty: string;\n    public tokenAPIHeader: string;\n    public tags: any;\n\n    constructor(name: string,\n                address: string,\n                user: string,\n                credential: string,\n                credentialType: string,\n                description: string,\n                tokenAPI: string,\n                tokenAPIProperty: string,\n                tokenAPIHeader: string,\n                tags: any) {\n\n        this.name = name;\n        this.address = address;\n        this.user = user;\n        this.credential = credential;\n        this.credentialType = credentialType;\n        this.description = description;\n        this.tokenAPI = tokenAPI;\n        this.tokenAPIProperty = tokenAPIProperty;\n        this.tokenAPIHeader = tokenAPIHeader;\n        Object.assign(this, tags);\n        this.id = 0;\n    }\n\n}\n\nexport const credentialScheme = ['none', 'password', 'ssh key', 'OAuth Secret'];\n\n"
  },
  {
    "path": "src/app/configuration/tab-endpoint/endpoint.service.ts",
    "content": "/**\n * Created by jayhamilton on 2/7/17.\n */\nimport {Injectable} from '@angular/core';\n\nimport {Observable} from 'rxjs';\nimport {EndPoint} from './endpoint.model';\nimport {HttpClient} from '@angular/common/http';\n\n\n@Injectable()\nexport class EndPointService {\n\n\n    constructor(private _http: HttpClient) {\n    }\n\n    getEndPoints() {\n        if (localStorage.getItem('endpoint') == null) {\n\n            return new Observable(observer => {\n                const base = {endPoint: []};\n                const mockBarChart = new EndPoint(\n                    'Chart Mock Bar Data Source',\n                    '/assets/api/chart-mock-bar-model.json',\n                    'test user',\n                    'testCredential',\n                    'unknown',\n                    'Predefined data source that cannot be modified or removed.',\n                    'token API',\n                    'token API Header',\n                    'token API Property',\n                    {'tags':[{'name':'bar'},{'name':'chart'}]}\n                );\n                base.endPoint.push(mockBarChart);\n                const mockPieChart = new EndPoint(\n                    'Chart Mock Pie Data Source',\n                    '/assets/api/chart-mock-pie-model.json',\n                    'test user',\n                    'testCredential',\n                    'unknown',\n                    'Predefined data source that cannot be modified or removed',\n                    'token API',\n                    'token API Header',\n                    'token API Property',\n                    {'tags':[{'name':'pie'},{'name':'chart'}]}\n                );\n                base.endPoint.push(mockPieChart);\n                const memoryEndpoint = new EndPoint(\n                    'Memory',\n                    '/metric?measure=memory',\n                    'test user',\n                    'testCredential',\n                    'unknown',\n                    'Predefined data source that cannot be modified or removed',\n                    'token API',\n                    'token API Header',\n                    'token API Property',\n                    {'tags':[{'name':'memory'}]}\n                );\n                base.endPoint.push(memoryEndpoint);\n\n                localStorage.setItem('endpoint', JSON.stringify(base));\n                observer.next(base);\n                return () => {\n                };\n            });\n        } else {\n\n            return new Observable(observer => {\n                const data = JSON.parse(localStorage.getItem('endpoint'));\n                observer.next(data);\n                return () => {\n                };\n            });\n\n        }\n    }\n\n    saveEndPoint(endpoint: any) {\n\n        return new Observable(observer => {\n\n            localStorage.setItem('endpoint', JSON.stringify(endpoint));\n            observer.next({});\n            return () => {\n            };\n\n        });\n\n    }\n}\n"
  },
  {
    "path": "src/app/configuration/tab-endpoint/endpointDetail.component.ts",
    "content": "/**\n * Created by jayhamilton on 5/16/17.\n */\nimport {AfterViewInit, Component, EventEmitter, Input, OnChanges, Output} from '@angular/core';\nimport {FormGroup, FormBuilder, Validators} from '@angular/forms';\n\nimport {credentialScheme, EndPoint, TAG} from './endpoint.model';\nimport {COMMA, ENTER} from '@angular/cdk/keycodes';\nimport {MatChipInputEvent} from \"@angular/material\";\n\n@Component({\n    selector: 'app-endpoint-detail',\n    moduleId: module.id,\n    templateUrl: './endpointDetail.html',\n    styleUrls: ['./styles.css']\n})\n\n/**\n *\n * TODO- Redo this entire file and add a state machine. This code is very fragile.\n */\n\nexport class EndPointDetailComponent implements OnChanges, AfterViewInit {\n\n    @Input() currentEndPoint: EndPoint;\n\n    @Output() createEvent: EventEmitter<EndPoint> = new EventEmitter();\n    @Output() updateEvent: EventEmitter<EndPoint> = new EventEmitter();\n    @Output() deleteEvent: EventEmitter<EndPoint> = new EventEmitter();\n\n    preDefinedEndPoints = [\"memory\", \"mock\"];\n\n    currentState: string;\n    preDefined = false;\n\n    endPointForm: FormGroup;\n    credentialScheme = credentialScheme;\n    useCredentials = false;\n\n    //chip/tag list control\n    selectable = true;\n    removable = true;\n    visible = true;\n    addOnBlur = false;\n    tagPlaceHolderText = '';\n    formTags = {tags: []};\n\n    readonly separatorKeysCodes: number[] = [ENTER, COMMA];\n\n    addTag(event: MatChipInputEvent): void {\n        const input = event.input;\n        const value = event.value;\n\n        // Add tag\n        if ((value || '').trim()) {\n            this.formTags.tags.push({name: value.trim()});\n        }\n\n        // Reset the input value\n        if (input) {\n            input.value = '';\n        }\n\n        if (this.currentState == 'reset') {\n            this.currentState = 'update';\n        }\n    }\n\n    removeTag(tag: TAG): void {\n        const index = this.formTags.tags.indexOf(tag);\n\n        if (index >= 0) {\n            this.formTags.tags.splice(index, 1);\n        }\n        if (this.currentState == 'reset') {\n            this.currentState = 'update';\n        }\n    }\n\n    checkPredefinition() {\n\n        this.preDefined = false;\n        for (let x = 0; x < this.preDefinedEndPoints.length; x++) {\n            if (this.currentEndPoint.name.toLocaleLowerCase().trim().indexOf(this.preDefinedEndPoints[x].toLocaleLowerCase().trim()) >= 0) {\n\n                this.disableControls();\n                this.preDefined = true;\n            }\n        }\n    }\n\n    ngAfterViewInit() {\n\n        this.checkPredefinition();\n    }\n\n    ngOnChanges() {\n\n        this.enableControls();\n        this.resetForm();\n        this.populateFormWithCurrentEndpointValues();\n        this.checkPredefinition();\n    }\n\n    populateFormWithCurrentEndpointValues() {\n\n        this.endPointForm.setValue({\n            name: this.currentEndPoint.name,\n            address: this.currentEndPoint.address,\n            user: this.currentEndPoint.user,\n            credentialType: this.currentEndPoint.credentialType,\n            credential: this.currentEndPoint.credential,\n            description: this.currentEndPoint.description,\n            tokenAPI: this.currentEndPoint.tokenAPI,\n            tokenAPIProperty: this.currentEndPoint.tokenAPIProperty,\n            tokenAPIHeader: this.currentEndPoint.tokenAPIHeader\n        });\n        this.formTags.tags = this.currentEndPoint.tags.slice();\n    }\n\n    constructor(private fb: FormBuilder) {\n\n        let me = this;\n\n        this.createForm();\n\n        this.endPointForm.valueChanges.forEach(\n            (value => {\n                if (this.currentState !== 'create') {\n                    me.setFormState();\n                }\n            })\n        );\n    }\n\n    disableControls() {\n\n        this.endPointForm.get('name').disable();\n        this.endPointForm.get('address').disable();\n        this.endPointForm.get('description').disable();\n        this.removable = false;\n        this.selectable = false;\n        this.tagPlaceHolderText = \"\";\n\n    }\n\n    enableControls() {\n\n        this.endPointForm.get('name').enable();\n        this.endPointForm.get('address').enable();\n        this.endPointForm.get('description').enable();\n        this.removable = true;\n        this.selectable = true;\n        this.tagPlaceHolderText = \"Add tag...\";\n\n    }\n\n\n    setFormState() {\n\n        /**\n         * todo - implement state machine\n         */\n\n        if (this.endPointForm.get('name').pristine) {\n\n            // something other than name changed so this must be an update\n            if (this.endPointForm.dirty) {\n                this.currentState = 'update';\n            }\n        } else {\n            // name change so assume user wants to perform save as\n            this.currentState = 'save as';\n        }\n\n        // reset state when a form is clean\n        if (this.endPointForm.pristine) {\n            this.currentState = 'reset';\n        }\n    }\n\n    createForm() {\n\n        this.endPointForm = this.fb.group({\n\n            name: ['', Validators.required],\n            address: ['', Validators.required],\n            user: '',\n            credentialType: '',\n            credential: '',\n            tokenAPI: '',\n            tokenAPIProperty: '',\n            tokenAPIHeader: '',\n            description: ''\n        });\n    }\n\n    createEndPoint() {\n\n        this.enableControls();\n\n        const ep: EndPoint = new EndPoint(\n            this.endPointForm.value.name,\n            this.endPointForm.value.address,\n            this.endPointForm.value.user,\n            this.endPointForm.value.credential,\n            this.endPointForm.value.credentialType,\n            this.endPointForm.value.description,\n            this.endPointForm.value.tokenAPI,\n            this.endPointForm.value.tokenAPIProperty,\n            this.endPointForm.value.tokenAPIHeader,\n            this.formTags\n        );\n\n        this.createEvent.emit(ep);\n        this.currentState = 'reset';\n    }\n\n    updateEndPoint() {\n\n        this.currentEndPoint.name = this.endPointForm.value.name;\n        this.currentEndPoint.address = this.endPointForm.value.address;\n        this.currentEndPoint.user = this.endPointForm.value.user;\n        this.currentEndPoint.credential = this.endPointForm.value.credential;\n        this.currentEndPoint.credentialType = this.endPointForm.value.credentialType;\n        this.currentEndPoint.description = this.endPointForm.value.description;\n        this.currentEndPoint.tokenAPI = this.endPointForm.value.tokenAPI;\n        this.currentEndPoint.tokenAPIProperty = this.endPointForm.value.tokenAPIProperty;\n        this.currentEndPoint.tokenAPIHeader = this.endPointForm.value.tokenAPIHeader;\n        this.currentEndPoint.tags = this.formTags.tags.slice();\n\n        this.updateEvent.emit(this.currentEndPoint);\n        this.currentState = 'reset';\n    }\n\n    newEndPoint() {\n\n        this.enableControls();\n        this.resetForm();\n        this.selectable = true;\n        this.removable = true;\n        this.preDefined = false;\n        this.tagPlaceHolderText = \"Add tag...\"\n        /**\n         * The create state is used to display the save icon even if the form is being edited\n         * todo - implmenet state machine\n         */\n        this.currentState = 'create';\n    }\n\n    resetEndPoint() {\n        this.ngOnChanges();\n\n    }\n\n    deleteEndPoint() {\n\n        this.deleteEvent.emit(this.currentEndPoint);\n        this.resetForm();\n    }\n\n    resetForm() {\n        this.endPointForm.reset();\n        if (this.formTags.tags && this.formTags.tags.length) {\n            this.formTags.tags = [];\n        }\n    }\n}\n\n"
  },
  {
    "path": "src/app/configuration/tab-endpoint/endpointDetail.html",
    "content": "<div class=\"ui right aligned grid\">\n    <div class=\"right aligned column\">\n\n        <span *ngIf=\"currentState == 'save as' && endPointForm.valid\">\n         <a mat-mini-fab routerLink=\".\" color='primary' (click)=\"createEndPoint()\"><mat-icon>content_copy</mat-icon></a>\n            &nbsp;save as&nbsp;\n        </span>\n\n        <span *ngIf=\"currentState == 'update' && endPointForm.valid\">\n            <a mat-mini-fab routerLink=\".\" color='primary' (click)=\"updateEndPoint()\"><mat-icon>save</mat-icon></a>\n            &nbsp;update&nbsp;\n        </span>\n\n\n        <span *ngIf=\"currentState == 'create' && endPointForm.valid\">\n            <a mat-mini-fab routerLink=\".\" color='primary' (click)=\"createEndPoint()\"><mat-icon>save</mat-icon></a>\n            &nbsp;save&nbsp;\n        </span>\n\n        <span *ngIf=\"endPointForm.dirty && currentState != 'create'\">\n            <a mat-mini-fab routerLink=\".\" color='primary' (click)=\"resetEndPoint()\"><mat-icon>undo</mat-icon></a>\n            &nbsp;undo&nbsp;\n        </span>\n\n        <span>\n            <a mat-mini-fab routerLink=\".\" color='primary' (click)=\"newEndPoint()\"><mat-icon>add</mat-icon></a>\n            &nbsp;create&nbsp;\n        </span>\n\n        <span *ngIf=\"currentEndPoint.name !='' && currentState != 'create' && preDefined == false\">\n            <a mat-mini-fab routerLink=\".\" (click)=\"deleteEndPoint()\"> <mat-icon>clear</mat-icon></a>\n            &nbsp;remove&nbsp;\n        </span>\n\n    </div>\n</div>\n\n<br>\n\n<form [formGroup]=\"endPointForm\" novalidate class=\"ui form\">\n    <div class=\"field\">\n        <div class=\"ui left icon input\">\n            <input formControlName=\"name\"  type=\"text\" placeholder=\"Name\">\n            <i class=\"tag icon\"></i>\n        </div>\n    </div>\n\n    <div class=\"field\">\n        <div class=\"ui left icon input\">\n            <input formControlName=\"address\"  type=\"text\" placeholder=\"URL\">\n            <i class=\"marker icon\"></i>\n        </div>\n    </div>\n    <div class=\"field\">\n        <div class=\"ui\">\n            <textarea rows=\"2\" class=\"form-control\" formControlName=\"description\" placeholder=\"Description\"></textarea>\n        </div>\n    </div>\n    <mat-form-field  class=\"example-chip-list\">\n        <mat-chip-list #chipList>\n            <mat-chip *ngFor=\"let tag of formTags.tags\" [selectable]=\"selectable\"\n                      [removable]=\"removable\" (removed)=\"removeTag(tag)\">\n                {{tag.name}}\n                <mat-icon matChipRemove *ngIf=\"removable\">cancel</mat-icon>\n            </mat-chip>\n            <input [disabled]=\"preDefined\" type=\"\" placeholder={{tagPlaceHolderText}}\n                   [matChipInputFor]=\"chipList\"\n                   [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n                   [matChipInputAddOnBlur]=\"addOnBlur\"\n                   (matChipInputTokenEnd)=\"addTag($event)\">\n        </mat-chip-list>\n    </mat-form-field>\n\n    <div *ngIf=\"useCredentials\">\n            <div class=\"field\">\n                <label>\n                    <select class=\"ui transparent\" formControlName=\"credentialType\">\n                        <option *ngFor=\"let credentialType of credentialScheme\" [value]=\"credentialType\">\n                            {{credentialType}}\n                        </option>\n                    </select>\n                </label>\n            </div>\n            <div class=\"field\">\n                <div class=\"ui left icon input\">\n                    <input formControlName=\"user\" type=\"text\" placeholder=\"User\">\n                    <i class=\"user icon\"></i>\n                </div>\n            </div>\n\n            <div class=\"field\">\n                <div class=\"ui left icon input\">\n                    <input formControlName=\"credential\" type=\"password\" placeholder=\"Credential\">\n                    <i class=\"key icon\"></i>\n                </div>\n            </div>\n\n            <div class=\"field\">\n                <div class=\"ui left icon input\">\n                    <input formControlName=\"tokenAPI\" type=\"string\" placeholder=\"Token API\">\n                    <i class=\"key icon\"></i>\n                </div>\n            </div>\n            <div class=\"field\">\n                <div class=\"ui left icon input\">\n                    <input formControlName=\"tokenAPIProperty\" type=\"string\" placeholder=\"Token API Property\">\n                    <i class=\"key icon\"></i>\n                </div>\n            </div>\n\n        </div>\n</form>\n\n\n\n\n\n"
  },
  {
    "path": "src/app/configuration/tab-endpoint/styles.css",
    "content": "\ntd.selected {\n    background-color: #3f51b5 !important;\n    color: white;\n    font-weight: bold;\n\n}\n\n.ui.table {\n    border: none !important;\n    color: rgba(97, 97, 97, 0.68) !important;\n}\n\n.ui.form .field > label {\n    color: rgba(97, 97, 97, 0.68) !important;\n    line-height: 3em !important;\n}\n\n.ui.form select{\n    color: rgba(97, 97, 97, 0.68) !important;\n    height: 3em !important;\n}\n\n.ui.form input{\n\n    color: rgba(97, 97, 97, 0.68) !important;\n\n}\n.ui.table tr td{\n    border:none !important;\n}\n\n.ui.form textarea{\n\n    color: rgba(97, 97, 97, 0.68) !important;\n}\n\ntr {\n     cursor: pointer;\n}\n.example-chip-list {\n    width: 100%;\n}\n"
  },
  {
    "path": "src/app/configuration/tab-endpoint/view.html",
    "content": "<div *ngIf=\"env.boardConfiguration.endpoint == true\" class=\"ui equal width fields grid container\">\n\n    <div class=\"field six wide column\">\n\n        <table class=\"ui selectable celled table\">\n            <tbody>\n            <tr *ngFor=\"let endPoint of endPoints\" (click)=\"setSelectedEndPoint(endPoint)\">\n                <td [ngClass]=\"{'selected': endPoint.name == currentEndPoint.name}\">{{endPoint.name}}</td>\n            </tr>\n            </tbody>\n        </table>\n    </div>\n    <div class=\"field ten wide column\">\n\n        <div *ngIf=\"currentEndPoint\">\n\n            <app-endpoint-detail [currentEndPoint]=currentEndPoint\n                            (createEvent)=\"createEndPoint($event)\"\n                            (updateEvent)=\"updateEndPoint($event)\"\n                            (deleteEvent)=\"deleteEndPoint($event)\"\n            ></app-endpoint-detail>\n        </div>\n\n    </div>\n</div>\n\n<div *ngIf=\"env.boardConfiguration.endpoint == false\">\n    This feature is not ready yet!\n</div>\n\n\n\n"
  },
  {
    "path": "src/app/configuration/tab-options/options-configuration-tab.component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    Component\n} from '@angular/core';\nimport {OptionsService} from \"./service\";\nimport {ToastService} from \"../../toast/toast.service\";\n\n@Component({\n    selector: 'app-options-config-tab',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css']\n})\nexport class OptionsConfigurationTabComponent {\n\n    enableHover: boolean;\n    displayGadgetOptionsInSideBar:boolean;\n\n    constructor(private _optionsService: OptionsService, private _toastService: ToastService) {\n\n        this.enableHover = this._optionsService.getBoardOptions()['enableHover'];\n        this.displayGadgetOptionsInSideBar = this._optionsService.getBoardOptions()['displayGadgetOptionsInSideBar'];\n    }\n\n    onHooverOptionChange(value) {\n\n        this._optionsService.setBoardOptions(\n            {\n                \"enableHover\": value['checked'],\n                \"displayGadgetOptionsInSideBar\": this.displayGadgetOptionsInSideBar\n\n            });\n        this._toastService.sendMessage(\"The board configuration has changed!\",null);\n    }\n\n    onDisplayGadgetOptionsInSideBarChange(value) {\n\n        this._optionsService.setBoardOptions( {\n            \"enableHover\": this.enableHover,\n            \"displayGadgetOptionsInSideBar\": value['checked']\n\n        });\n        this._toastService.sendMessage(\"The board configuration has changed!\",null);\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/configuration/tab-options/service.ts",
    "content": "import {Injectable} from \"@angular/core\";\nimport {Subject,Observable} from \"rxjs\";\n\n\n@Injectable()\nexport class OptionsService {\n\n    optionsCollectionName = 'dashboardOptions';\n    defaultOptions = {\n        'enableHover': false,\n        'displayGadgetOptionsInSideBar': false\n    };\n\n    private globalOptionsChangeEventSubject: Subject<any> = new Subject<any>();\n\n    constructor() {\n    }\n\n    public getBoardOptions() {\n\n        let databaseOptions = JSON.parse(localStorage.getItem(this.optionsCollectionName));\n\n        if (databaseOptions == null) {\n            this.persistDefautBoardOptions();\n            return this.defaultOptions;\n        } else {\n            return databaseOptions;\n        }\n    }\n\n    private persistDefautBoardOptions(){\n\n        localStorage.setItem(this.optionsCollectionName, JSON.stringify(this.defaultOptions))\n\n    }\n    public setBoardOptions(options: any) {\n\n        /**\n         * Todo this will need to change to support the update to individual options. Currently there is only one\n         * option but once there is more than one this method must change to take the input and update just that\n         * property of the options object.\n         */\n\n        localStorage.removeItem(this.optionsCollectionName);\n\n        /**\n         *  Raise an event to listeners, primarily the gadgets, when the global options change. The listeners can use\n         * the event to change their behavior\n         */\n        this.globalOptionsChangeEventSubject.next(options);\n\n        return localStorage.setItem(this.optionsCollectionName, JSON.stringify(options));\n\n    }\n\n\n    /**\n     * The gadget-base can use this method to subscribe to events that are created when the global options change.\n    */\n    listenForGlobalOptionsChanges(): Observable<string> {\n        return this.globalOptionsChangeEventSubject.asObservable();\n    }\n}\n"
  },
  {
    "path": "src/app/configuration/tab-options/styles.css",
    "content": ""
  },
  {
    "path": "src/app/configuration/tab-options/view.html",
    "content": "<br>\nThe following options control various aspects of the board's and gadget's behavior. Changes take effect immediately.\n<br>\n<br>\n\n<mat-slide-toggle\n        [checked]=\"enableHover\"\n        (change)=\"onHooverOptionChange($event)\">\n    Always show the gadget buttons in the title. By default buttons show/hide when you hover over the title.\n</mat-slide-toggle>\n<br>\n<br>\n<mat-slide-toggle\n        [checked]=\"displayGadgetOptionsInSideBar\"\n        (change)=\"onDisplayGadgetOptionsInSideBarChange($event)\">\n    (Experimental) When set the options are displayed in the side bar. Otherwise it is displayed within the gadget.\n</mat-slide-toggle>"
  },
  {
    "path": "src/app/configuration/tabs.model.ts",
    "content": "export const tabsModel: ({ groupId: string; displayName: string } | { groupId: string; displayName: string })[] = [\n    {\n        groupId: 'boards',\n        displayName: 'Boards'\n    },\n    {\n        groupId: 'options',\n        displayName: 'Options'\n    },\n    {\n        groupId: 'endpoint',\n        displayName: 'Data Source Registration'\n    },\n    {\n        groupId: 'ai',\n        displayName: 'AI Configuration'\n    }\n\n];\n"
  },
  {
    "path": "src/app/configuration/view.html",
    "content": "<div class=\"ui long modal\" #boardconfigmodal_tag>\n    <div class=\"header\">\n        <h2>{{modalheader}}</h2>\n    </div>\n\n\n    <div class=\"ui top attached tabular menu\">\n\n        <a *ngFor=\"let tab of tabsModel; let i = index\" class=\"item\"\n           [ngClass]=\"{'active': tab.displayName == currentTab }\"\n           attr.data-tab=\"{{tab.groupId}}\" (click)=\"setCurrentTab(i)\">{{tab.displayName}}</a>\n\n    </div>\n\n    <div *ngFor=\"let tab of tabsModel; let i = index\" [ngClass]=\"{'active': tab.displayName == currentTab }\"\n         class=\"ui bottom attached tab segment\"\n         attr.data-tab=\"{{tab.groupId}}\" [@contentSwitch]=\"tab.displayName == currentTab ? 'active':'inactive'\">\n\n\n        <div *ngIf=\"tab.groupId == 'boards'\">\n\n            <app-boards-config-tab  (dashboardCreateEvent)=\"createBoard($event)\"\n                                   (dashboardEditEvent)=\"editBoard($event)\"\n                                   (dashboardDeleteEvent)=\"deleteBoard($event)\"\n                                   [dashboardList]=\"dashboardList\"></app-boards-config-tab>\n        </div>\n\n        <div *ngIf=\"tab.groupId == 'endpoint'\">\n\n            <app-endpoint-config-tab></app-endpoint-config-tab>\n\n        </div>\n\n        <div *ngIf=\"tab.groupId == 'ai'\">\n\n            <app-ai-config-tab></app-ai-config-tab>\n\n        </div>\n\n        <div *ngIf=\"tab.groupId == 'options'\">\n\n            <app-options-config-tab></app-options-config-tab>\n\n        </div>\n    </div>\n\n\n    <div class=\"actions\">\n        <button class=\"ui button\" (click)=\"hideMessageModal()\">Close </button>\n    </div>\n</div>"
  },
  {
    "path": "src/app/datalist/action-model.ts",
    "content": "interface ActionInterface {\n    name: string;\n    item: any;\n}\n"
  },
  {
    "path": "src/app/datalist/data-list.component.ts",
    "content": "import {Component, ContentChild, Input, TemplateRef} from '@angular/core';\nimport {Facet} from '../facet/facet-model';\n\n@Component({\n    selector: 'app-data-list',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css']\n})\nexport class DataListComponent {\n\n    @Input() objectList: any[];\n    @Input() objectTitleList: string[];\n    @Input() placeHolderText: string;\n    @Input() layoutColumnOneWidth: string;\n    @Input() layoutColumnTwoWidth: string;\n    @Input() listHeader: string;\n    @Input() typeAheadIsInMenu: boolean;\n    @Input() facetTags: Array<Facet>;\n\n    @ContentChild(TemplateRef) template: TemplateRef<any>;\n\n\n    color = 'white';\n    objectListCopy: any[] = [];\n\n    filterListByTags(filterList: string[]) {\n\n        this.copyObjectList();\n        this.objectList = this.objectListCopy.filter(object => {\n\n            let tagFound = false;\n\n            if (!filterList.length) {\n                return true;\n            } else {\n                object.tags.forEach(tag => {\n\n                    filterList.forEach(filter => {\n\n                        if (tag.name.toLocaleLowerCase() === filter.toLocaleLowerCase()) {\n                            tagFound = true;\n                        }\n                    });\n                });\n\n                return tagFound;\n            }\n        });\n\n    }\n\n    filterListBySearchString(searchString: string) {\n\n        this.copyObjectList();\n        this.objectList = this.objectListCopy.filter(object => {\n\n            if (searchString.localeCompare('') === 0) {\n                return true;\n            } else {\n\n                if (object.name.toLowerCase().indexOf(searchString.toLowerCase()) !== -1) {\n\n                    return true;\n                }\n            }\n\n        });\n    }\n\n    /**\n     * todo - find a better way to manage the list that is displayed and filtered.\n     */\n    copyObjectList() {\n        if (this.objectListCopy.length === 0) {\n            this.objectList.forEach(item => {\n                this.objectListCopy.push(item);\n            });\n        }\n    }\n}\n\n"
  },
  {
    "path": "src/app/datalist/data-list.module.ts",
    "content": "import {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {FacetModule} from '../facet/facet.module';\nimport {HttpClientModule} from '@angular/common/http';\nimport {TypeAheadInputModule} from '../typeahead-input/typeahead-input.module';\nimport {DataListComponent} from './data-list.component';\nimport {BrowserAnimationsModule} from '@angular/platform-browser/animations';\n\n@NgModule({\n    imports: [\n        CommonModule,\n        FacetModule,\n        TypeAheadInputModule,\n        HttpClientModule,\n        BrowserAnimationsModule\n    ],\n    declarations: [\n        DataListComponent\n    ],\n    providers: [],\n    exports: [\n        DataListComponent\n    ]\n})\nexport class DataListModule {\n}\n"
  },
  {
    "path": "src/app/datalist/styles.css",
    "content": ".content {\n    background-color:#f7f7f7;\n    margin-top: 25px;\n    margin-left: 25px;\n    padding:5px;\n}\n\nhr {\n    height: 2px !important;\n    color: rgba(110, 110, 110, 0.1) !important;\n    background: rgba(110, 110, 110, 0.1) !important;\n    font-size: 0;\n    border: 0;\n\n}\n.list-content{\n    max-height: 700px;\n    overflow-y: scroll;\n    margin-top: 20px;\n    padding-right: 10px\n}\n"
  },
  {
    "path": "src/app/datalist/view.html",
    "content": "<div class=\"content\">\n    <div class=\"ui grid\">\n        <div class=\"{{layoutColumnOneWidth}} wide column\">\n            <app-typeahead-input\n                    [searchList]=\"objectTitleList\"\n                    [placeHolderText]=\"placeHolderText\"\n                    [typeAheadIsInMenu]=\"typeAheadIsInMenu\"\n                    (selectionEvent)=\"filterListBySearchString($event)\">\n            </app-typeahead-input>\n            <app-filter-list #filterComponent\n                             [facet_tags]=\"facetTags\"\n                             (tagSelectEvent)=\"filterTag.updateFilterList($event)\">\n\n            </app-filter-list>\n        </div>\n        <div class=\"{{layoutColumnTwoWidth}} wide column\">\n            <br>\n            <app-filter-tag #filterTag\n                            (updateFilterListEvent)=\"filterListByTags($event)\">\n\n            </app-filter-tag>\n\n            <div class=\"list-content\">\n                <ng-template ngFor [ngForOf]=\"objectList\" [ngForTemplate]=\"template\"></ng-template>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "src/app/detail/detail.component.ts",
    "content": "import {Component, OnInit} from '@angular/core';\nimport {ActivatedRoute, NavigationEnd, Router} from \"@angular/router\";\nimport {EndPointService} from \"../configuration/tab-endpoint/endpoint.service\";\nimport {RuntimeService} from \"../services/runtime.service\";\nimport {DetailService} from \"./service\";\n\n\n/**a\n * Detail component\n *\n */\n@Component({\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['styles.css']\n})\nexport class DetailComponent implements OnInit {\n\n    chartType: string;\n    chartSeries: string;\n    chartMetric: string;\n    endPointName: string;\n    data = [];\n    searchText: string;\n    navRoutes: Array<string> = [];\n    navigationSubscription: any;\n    objectAsArray = [];\n\n\n    constructor(private _router: Router,\n                private _route: ActivatedRoute,\n                private _endPointService: EndPointService,\n                private _detailService: DetailService\n    ) {\n        this.navigationSubscription = this._router.events.subscribe((e: any) => {\n            // If it is a NavigationEnd event re-initalise the component\n            if (e instanceof NavigationEnd) {\n                this.getObjectsByMetric(true);\n            }\n        });\n    }\n\n    ngOnInit() {\n        this.chartType = this._route.snapshot.queryParams['chartType'];\n        this.chartSeries = this._route.snapshot.queryParams['chartSeries'];\n        this.chartMetric = this._route.snapshot.queryParams['chartMetric'];\n        this.endPointName = this._route.snapshot.queryParams['endPointName'];\n        this.getObjectsByMetric(false);\n\n    }\n\n    getObject(record: any) {\n        this.clearDetailDisplay();\n\n        Object.keys(record).forEach(key => {\n\n            if (key.indexOf(\"link\") < 0) {\n                this.objectAsArray.push({\"key\": key, \"value\": record[key]});\n            }\n        })\n    }\n\n    getObjectsByHateoasLink(detail: any) {\n        this.clearDetailDisplay();\n\n        let href = \"\";\n        detail.links.forEach(link => {\n            if (link.rel == 'self') {\n                href = link.href;\n            }\n        });\n\n        let navArray = href.split('/');\n\n        //trying to get data for the current record so do nothing. Avoid this altogether by removing the link from the table.\n        if (navArray[navArray.length - 1] == this.navRoutes[this.navRoutes.length - 1]) {\n            return;\n        }\n\n        this.navRoutes.push(navArray[navArray.length - 1]);\n\n        this._detailService.getDetail(href).subscribe(data => {\n            this.data = data.slice();\n        });\n    }\n\n\n    getObjectsByMetric(isReload: boolean) {\n        this.clearDetailDisplay();\n\n        this._detailService.getDetailByChartSeriesSelected(this.chartType, this.chartSeries, this.chartMetric, this.endPointName).subscribe(data => {\n            this.data = data.slice();\n        });\n\n        if (!isReload) {\n            this.navRoutes.push(this.chartMetric);\n        } else {\n\n            /**\n             * todo - this won't work for many routes.\n             */\n            while (this.navRoutes.length > 1) {\n                this.navRoutes.splice(this.navRoutes.length - 1, 1);\n            }\n        }\n    }\n\n    goHome() {\n        this._router.navigate([\"/main-board\"]);\n    }\n\n    gotToRoute(nav: string, disabled: boolean) {\n\n        if (!disabled) {\n\n\n            this._router.navigate(['/detail'], {\n                queryParams:\n                    {\n                        chartType: this.chartType,\n                        chartSeries: this.chartSeries,\n                        chartMetric: this.chartMetric,\n                        endPointName: this.endPointName\n                    }\n            });\n        }\n    }\n\n    clearDetailDisplay() {\n        this.objectAsArray = [];\n    }\n}\n"
  },
  {
    "path": "src/app/detail/detail.model.ts",
    "content": "interface DetailModel {\n    name: string;\n    data: any;\n}\n"
  },
  {
    "path": "src/app/detail/detail.module.ts",
    "content": "import {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {MatCheckboxModule} from '@angular/material';\nimport {FormsModule} from '@angular/forms';\nimport {DetailComponent} from './detail.component';\nimport {DetailService} from \"./service\";\nimport {FilterPipe} from \"./filter.pipe\";\n\n\n@NgModule({\n    imports: [\n        CommonModule,\n        FormsModule,\n        MatCheckboxModule\n    ],\n    declarations: [\n        DetailComponent,\n        FilterPipe\n    ],\n    providers: [\n        DetailService\n    ],\n    exports: [\n        DetailComponent\n    ]\n})\nexport class DetailModule {\n}\n\n"
  },
  {
    "path": "src/app/detail/detail.resolver.ts",
    "content": "import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router';\nimport {Observable} from 'rxjs';\n\n\nexport class DetailResolver implements Resolve <DetailModel> {\n\n    data: DetailModel;\n\n    constructor(detailData: DetailModel) {\n        this.data = detailData;\n    }\n\n    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<DetailModel> | Promise<DetailModel> | DetailModel {\n\n        return this.data;\n    };\n\n}\n"
  },
  {
    "path": "src/app/detail/filter.pipe.ts",
    "content": "import { Pipe, PipeTransform } from '@angular/core';\n@Pipe({\n    name: 'filter'\n})\nexport class FilterPipe implements PipeTransform {\n    transform(items: any[], searchText: string): any[] {\n        if(!items) return [];\n        if(!searchText) return items;\n\n\n        searchText = searchText.toLowerCase();\n        return items.filter( it => {\n            return it.node.toLowerCase().includes(searchText)\n                || it.master.toLowerCase().includes(searchText)\n                || it.jobName.toLowerCase().includes(searchText)\n                || it.status.toLowerCase().includes(searchText);\n        });\n    }\n}\n"
  },
  {
    "path": "src/app/detail/service.ts",
    "content": "import {Injectable} from \"@angular/core\";\nimport {HttpClient, HttpParams} from \"@angular/common/http\";\nimport {RuntimeService} from \"../services/runtime.service\";\nimport {environment} from \"../../environments/environment\";\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class DetailService {\n\n    constructor(private _http: HttpClient) {\n        this.configure();\n    }\n    testURL = \"http://localhost:8080\";\n    detailURL= \"/detail\";\n\n    configure() {\n\n        if (!environment.production) {\n            this.detailURL = this.testURL + this.detailURL;\n        }\n\n    }\n    getDetailByChartSeriesSelected(chartType: string, chartSeries: string, chartMetric: string, endPointName: string) {\n\n        /**\n         * Todo - review these parameters and make them more meaningful. The goal is to send to the service\n         * a pameterized URL /endpointURL?detailParameter={value or id}\n         */\n        let p = new HttpParams();\n        p = p.append(\"detailParam\", chartSeries);\n        p = p.append(\"detailMetric\", chartMetric);\n\n        return this._http.get<Array<any>>(this.detailURL, {params: p})\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n\n    }\n    getDetail(url: string) {\n\n        return this._http.get<Array<any>>(url)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n\n    }\n\n    getRecord(url: string) {\n\n        return this._http.get<Array<any>>(url)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n\n    }\n}"
  },
  {
    "path": "src/app/detail/styles.css",
    "content": "a,\na label {\n    cursor: pointer;\n}\n\n.field {\n    background: #4a95c3;\n    color: white;\n}\n\n.ui .breadcrumb {\n    font-size: 1.28571429rem;\n}\n\n.detail-right-header {\n    color: #616161;\n    font-size: 1.2rem;\n    float: right;\n}\n\n.detail-left-header {\n    color: #616161;\n    font-size: 1.2rem;\n\n}\n.label{\n    background: transparent;\n}\n\n.active{\n    color:grey !important;\n    font-weight: normal !important;\n}"
  },
  {
    "path": "src/app/detail/view.html",
    "content": "<div class=\"ui centered stackable grid\" style=\"margin-left: 5px; margin-right: 5px\">\n    <div class=\"row\">\n        <div class=\"three wide column\"></div>\n        <div class=\"ten wide column left aligned\">\n\n            <div class=\"ui breadcrumb\">\n                <a class=\"section\" (click)=\"goHome()\">Board</a>\n\n                <span *ngFor=\"let nav of navRoutes,let i = index\">\n                    <span class=\"divider\">/</span>\n                    <a class=\"section\" (click)=\"gotToRoute(nav, navRoutes.length -1 == i)\"\n                           [ngClass]=\"{'active': navRoutes.length -1 == i }\">{{nav}}</a>\n                </span>\n\n            </div>\n\n            <div class=\"ui segment\">\n                <div class=\"ui top right attached label\"><a href=\"http://localhost:8080/detail/downloadFile\" target=\"_self\" ><i class=\"big grey download icon\"></i></a></div>\n\n                <div class=\"ui  basic segment\">\n                     <span class=\"detail-left-header\">\n                        Type: {{chartSeries}}\n                    </span>\n                    <span class=\"detail-right-header\">\n                       Count: {{data.length}} Tasks\n                    </span>\n\n                </div>\n                <div class=\"ui fluid icon input\">\n                    <i class=\"search icon\"></i>\n                    <input [(ngModel)]=\"searchText\" placeholder=\"search text goes here\">\n                </div>\n                <table class=\"ui celled compact fixed table\">\n                    <thead>\n                    <tr>\n                        <th></th>\n                        <th style=\"text-align: center\">Status</th>\n                        <th>Master</th>\n                        <th>Job Name</th>\n                        <th>Sub Type</th>\n                        <th>Job Id</th>\n                        <th>Task Id</th>\n                        <th>Node</th>\n                        <th>Disk</th>\n                        <th>Task Start</th>\n                        <th>Task End</th>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <tr *ngFor=\"let task of data | filter : searchText; let i = index \">\n                        <td [ngClass]=\"{'negative': task.status != 'Completed', 'positive': task.status == 'Completed' }\">\n                            {{i + 1}}\n                        </td>\n                        <td style=\"text-align: center\"><i class=\"icon large \"[ngClass]=\"{\n                        'red ban': task.status != 'Completed',\n                        'green check': task.status == 'Completed'\n                        }\"></i></td>\n                        <td>{{task.master}}</td>\n                        <td>{{task.jobName}}</td>\n                        <td>{{task.subType}}</td>\n                        <td><a (click)=\"getObjectsByHateoasLink(task)\">{{task.jobId}}</a></td>\n                        <td><a (click)=\"getObject(task)\">{{task.taskId}}</a></td>\n                        <td>{{task.node}}</td>\n                        <td>{{task.disk}}</td>\n                        <td>{{task.taskStart}}</td>\n                        <td>{{task.taskEnd}}</td>\n                    </tr>\n                    </tbody>\n                </table>\n            </div>\n        </div>\n\n        <div class=\"three wide column\">\n            <div class=\"ui breadcrumb\">\n                &nbsp;\n            </div>\n            <div class=\"ui  segment\" *ngIf=\"objectAsArray.length\">\n                <div class=\"ui top right attached label\"><i class=\"big download icon\"></i></div>\n\n                <div class=\"ui  basic segment\">\n                    <span class=\"detail-left-header\">Detail</span>\n                </div>\n\n                <table class=\"ui celled compact fixed table\">\n                    <tr *ngFor=\"let property of objectAsArray; \">\n                        <td class=\"field\">{{property.key}}</td>\n                        <td>{{property.value}}</td>\n                    </tr>\n\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n\n"
  },
  {
    "path": "src/app/dynamic-form/dynamic-form-module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {DynamicFormComponent} from './dynamic-form.component';\nimport {DynamicFormPropertyComponent} from './dynamic-form-property.component';\nimport {PropertyControlService} from './property-control.service';\nimport {FormsModule, ReactiveFormsModule} from '@angular/forms';\n\n\n@NgModule({\n    imports: [\n        CommonModule,\n        FormsModule,\n        ReactiveFormsModule\n    ],\n    declarations: [\n        DynamicFormComponent,\n        DynamicFormPropertyComponent\n    ],\n    providers: [PropertyControlService],\n    exports: [\n        DynamicFormComponent,\n        DynamicFormPropertyComponent\n    ]\n})\nexport class DynamicFormModule {\n}\n"
  },
  {
    "path": "src/app/dynamic-form/dynamic-form-property.component.html",
    "content": "<div [formGroup]=\"form\">\n\n    <div class=\"field\">\n        <label [attr.for]=\"property.key\">{{property.label}}</label>\n\n        <div [ngSwitch]=\"property.controlType\">\n\n            <input *ngSwitchCase=\"'textbox'\"\n                   [formControlName]=\"property.key\"\n                   [id]=\"property.key\"\n                   [type]=\"property.type\">\n\n            <select *ngSwitchCase=\"'dropdown'\"\n                    [formControlName]=\"property.key\"\n                    [id]=\"property.key\">\n\n                <option *ngFor=\"let opt of property.options\"\n                        [value]=\"opt.value\">{{opt.key}}\n                </option>\n            </select>\n\n            <!--todo - fix checkbox type. The value is not properly set by the data so using hard coded type -->\n            <input *ngSwitchCase=\"'checkbox'\"\n                   [formControlName]=\"property.key\"\n                   [id]=\"property.key\"\n                   [type]=\"'checkbox'\"\n                   (change)=\"property.value = $event.target.checked\"\n                   [(ngModel)]=\"property.value\"\n                   [attr.checked]=\"property.value ? true : null\">\n\n            <input *ngSwitchCase=\"'number'\"\n                   [formControlName]=\"property.key\"\n                   [id]=\"property.key\"\n                   [type]=\"'number'\">\n\n\n            <input *ngSwitchCase=\"'hidden'\"\n                   [formControlName]=\"property.key\"\n                   [id]=\"property.key\"\n                   [type]=\"property.type\">\n\n            <select *ngSwitchCase=\"'dynamicdropdown'\"\n                    [formControlName]=\"property.key\"\n                    [id]=\"property.key\"\n                    (change)=\"property.value = $event.target.toString()\">\n\n                <option></option>\n                <option *ngFor=\"let opt of endPoints\"\n                        [value]=\"opt.name\">{{opt.name}}\n                </option>\n\n            </select>\n        </div>\n    </div>\n\n    <div [@showHideAnimation] class=\"ui error message\" *ngIf=\"!isValid\">{{property.label}} is required</div>\n\n\n</div>"
  },
  {
    "path": "src/app/dynamic-form/dynamic-form-property.component.ts",
    "content": "/**\n * Created by jayhamilton on 2/5/17.\n */\nimport {AfterViewInit, Component, Input} from '@angular/core';\nimport {FormGroup} from '@angular/forms';\nimport {PropertyBase} from './property-base';\nimport {EndPointService} from '../configuration/tab-endpoint/endpoint.service';\n\nimport {\n    style, trigger, animate, transition\n} from '@angular/animations';\n\n@Component({\n    moduleId: module.id,\n    selector: 'app-df-property',\n    templateUrl: './dynamic-form-property.component.html',\n    styleUrls: ['./styles-props.css'],\n    animations: [\n\n        trigger(\n            'showHideAnimation',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(750, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(750, style({opacity: 0}))\n                ])\n            ])\n    ]\n})\nexport class DynamicFormPropertyComponent implements AfterViewInit {\n    @Input() property: PropertyBase<any>;\n    @Input() form: FormGroup;\n    @Input() gadgetTags: any[];//todo - use to control what endpoints are displayed\n    endPoints: string[] = [];\n\n    get isValid() {\n\n        return this.form.controls[this.property.key].valid;\n    }\n\n    constructor(private endPointService: EndPointService) {\n\n        this.updateEndPointList();\n    }\n\n    updateEndPointList() {\n\n        this.endPointService.getEndPoints().subscribe(data => {\n\n            this.endPoints = data['endPoint'].slice();\n\n        });\n    }\n\n    ngAfterViewInit() {\n\n        //filter endpoints based on the gadgets tags\n\n        let me = this;\n        let eligibleEndpoints = [];\n\n        this.endPoints.forEach(function (point, index, object) {\n\n            let found = false;\n            point['tags'].forEach(tag => {\n\n                me.gadgetTags.forEach(_gt => {\n\n                    if (_gt.name.trim().toLowerCase() === tag.name.trim().toLowerCase()) {\n                        found = true;\n                    }\n                })\n            });\n\n            if (found) {\n               eligibleEndpoints.push(point);\n            }\n        });\n\n        this.endPoints = eligibleEndpoints.slice();\n\n    }\n}\n"
  },
  {
    "path": "src/app/dynamic-form/dynamic-form.component.html",
    "content": "<div class=\"ui form\" style=\"text-align: left !important\">\n    <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form\">\n\n        <div class=\"proppages ui top attached tabular menu\" #tabComponentTag>\n            <a *ngFor=\"let tab of propertyPages; let i = index\" class=\"item\" #tabComponentTag\n               [ngClass]=\"{'active': tab.groupId == currentTab }\"\n               attr.data-tab=\"{{tab.groupId}}\" (click)=\"setCurrentTab(tab)\">{{tab.displayName}} </a>\n        </div>\n\n        <div [@contentSwitch]=\"page.groupId == currentTab ? 'active':'inactive'\"\n             *ngFor=\"let page of propertyPages; let i = index\" [ngClass]=\"{'active': page.groupId == currentTab }\"\n             class=\"proppages ui bottom attached tab segment\"\n             attr.data-tab=\"{{page.groupId}}\">\n\n\n            <div *ngFor=\"let property of page.properties\"\n                 class=\"form-row\">\n                <app-df-property\n                        [property]=\"property\"\n                        [form]=\"form\"\n                        [gadgetTags]=\"gadgetTags\"\n                >\n\n                </app-df-property>\n                <br>\n            </div>\n\n        </div>\n        <div class=\"form-row field\">\n            <button class=\"ui green submit button\" type=\"submit\" [disabled]=\"!form.valid || !form.dirty\"> Save</button>\n        </div>\n    </form>\n\n    <div *ngIf=\"showMessage\" [@showHideAnimation] class=\"form-row\">\n        <br>\n        <div class=\"ui success message\">Saved!</div>\n    </div>\n\n</div>\n"
  },
  {
    "path": "src/app/dynamic-form/dynamic-form.component.ts",
    "content": "/**\n * Created by jayhamilton on 2/5/17.\n */\nimport {\n    Component, Input, OnInit, Output, EventEmitter,\n    ChangeDetectorRef, AfterViewInit\n} from '@angular/core';\n\nimport {\n    style, state, trigger, animate, transition\n} from '@angular/animations';\n\nimport {FormGroup} from '@angular/forms';\n\nimport {PropertyControlService} from './property-control.service';\nimport {ConfigurationService} from '../services/configuration.service';\nimport {EndPointService} from '../configuration/tab-endpoint/endpoint.service';\nimport {EndPoint} from '../configuration/tab-endpoint/endpoint.model';\n\n\n@Component({\n    /* solves error: Expression has changed after it was checked exception resolution - https://www.youtube.com/watch?v=K_BRcal-JfI*/\n    // changeDetection: ChangeDetectionStrategy.OnPush,\n    moduleId: module.id,\n    selector: 'app-dynamic-form',\n    templateUrl: './dynamic-form.component.html',\n    styleUrls: ['./styles-props.css'],\n    animations: [\n\n        trigger('contentSwitch', [\n            state('inactive', style({\n                opacity: 0\n            })),\n            state('active', style({\n                opacity: 1\n            })),\n            transition('inactive => active', animate('750ms ease-in')),\n            transition('active => inactive', animate('750ms ease-out'))\n        ]),\n        trigger(\n            'showHideAnimation',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(750, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(750, style({opacity: 0}))\n                ])\n            ])\n    ],\n    providers: [PropertyControlService]\n})\nexport class DynamicFormComponent implements OnInit, AfterViewInit {\n\n    @Input() gadgetTags: any[];//todo - use to control what endpoints are displayed\n    @Input() propertyPages: any[];\n    @Input() instanceId: number;\n    @Output() updatePropertiesEvent: EventEmitter<any> = new EventEmitter(true);\n    currentTab = 'run';\n    endPoints: EndPoint[];\n    state = 'inactive';\n    lastActiveTab = {};\n\n    form: FormGroup = new FormGroup({});\n    payLoad = '';\n    showMessage = false;\n\n    constructor(private pcs: PropertyControlService,\n                private configService: ConfigurationService,\n                private changeDetectionRef: ChangeDetectorRef) {\n    }\n\n\n    /* better solution that solves error: Expression has changed after it was checked exception resolution*/\n    ngAfterViewInit(): void {\n\n        this.changeDetectionRef.detectChanges();\n    }\n\n    ngOnInit() {\n\n        this.form = this.pcs.toFormGroupFromPP(this.propertyPages);\n\n    }\n\n    onSubmit() {\n\n        this.payLoad = JSON.stringify(this.form.value);\n\n        console.debug('Saving Form!');\n        this.updatePropertiesEvent.emit(this.payLoad);\n\n        console.debug('Sending configuration to the config service!');\n        this.configService.notifyGadgetOnPropertyChange(this.payLoad, this.instanceId);\n\n        if (this.payLoad) {\n            this.showMessage = true;\n\n            setTimeout(function() {\n                this.showMessage = false;\n            }.bind(this), 2000);\n        }\n    }\n\n    setCurrentTab(tab) {\n        this.currentTab = tab.groupId;\n\n    }\n\n    get isPropertyPageValid (){\n\n        return this.form.valid;\n    }\n}\n\n\n\n\n\n"
  },
  {
    "path": "src/app/dynamic-form/property-base.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nexport class PropertyBase<T> {\n    value: T;\n    key: string;\n    label: string;\n    required: boolean;\n    order: number;\n    controlType: string;\n    options:any;\n\n    constructor(props: {\n        value?: T,\n        key?: string,\n        label?: string,\n        required?: boolean,\n        order?: number,\n        controlType?: string,\n        options?:any\n    } = {},\n   ) {\n\n        this.value = props.value;\n        this.key = props.key || '';\n        this.label = props.label || '';\n        this.required = !props.required;\n        this.order = props.order === undefined ? 1 : props.order;\n        this.controlType = props.controlType || '';\n        this.options = props.options;\n\n    }\n}"
  },
  {
    "path": "src/app/dynamic-form/property-checkbox.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nimport {PropertyBase} from './property-base';\n\n\nexport class CheckboxProperty extends PropertyBase<boolean> {\n\n    controlType = 'checkbox';\n    type: string;\n\n    constructor(options: {} = {}) {\n\n        super(options);\n        this.type = 'checkbox'; // options['type'] || '';\n    }\n\n}"
  },
  {
    "path": "src/app/dynamic-form/property-control.service.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nimport {Injectable} from '@angular/core';\nimport {FormControl, FormGroup, Validators} from '@angular/forms';\n\n@Injectable()\nexport class PropertyControlService {\n\n    constructor() {\n    }\n\n\n    toFormGroupFromPP(propertyPages: any[]) {\n\n        const group: any = {};\n\n        propertyPages.forEach(propertyPage => {\n\n            propertyPage.properties.forEach(property => {\n                group[property.key] = property.required ? new FormControl(property.value\n                    || '', Validators.required) : new FormControl(property.value\n                    || '');\n            });\n\n        });\n\n        return new FormGroup(group);\n    }\n}\n"
  },
  {
    "path": "src/app/dynamic-form/property-dropdown.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nimport {PropertyBase} from './property-base';\n\nexport class DropdownProperty extends PropertyBase<string> {\n\n    controlType = 'dropdown';\n    options: {key: string, value: string}[] = [];\n\n    constructor(options: {} = {}) {\n        super(options);\n        this.options = options['options'] || [];\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/dynamic-form/property-dynamicdropdown.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nimport {PropertyBase} from './property-base';\n\nexport class DynamicDropdownProperty extends PropertyBase<string> {\n\n    controlType = 'dynamicdropdown';\n    options: {key: string, value: string}[] = [];\n\n    constructor(options: {} = {}) {\n        super(options);\n        this.options = options['options'] || [];\n    }\n}\n"
  },
  {
    "path": "src/app/dynamic-form/property-hidden.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nimport {PropertyBase} from './property-base';\n\n\nexport class HiddenProperty extends PropertyBase<string> {\n\n    controlType = 'hidden';\n    type: string;\n\n    constructor(options: {} = {}) {\n        super(options);\n        this.type = 'hidden';\n    }\n\n}\n"
  },
  {
    "path": "src/app/dynamic-form/property-number.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nimport {PropertyBase} from './property-base';\n\n\nexport class NumberProperty extends PropertyBase<number> {\n\n    controlType = 'number';\n    type: string;\n\n    constructor(options: {} = {}) {\n        super(options);\n        this.type = 'number'; // options['type']|| '';\n    }\n\n}\n"
  },
  {
    "path": "src/app/dynamic-form/property-textbox.ts",
    "content": "/**\n * Created by jayhamilton on 2/3/17.\n */\nimport {PropertyBase} from './property-base';\n\nexport class TextboxProperty extends PropertyBase<string> {\n\n    controlType = 'textbox';\n    type: string;\n\n    constructor(options: {} = {}) {\n        super(options);\n        this.type = options['type'] || '';\n    }\n\n}\n"
  },
  {
    "path": "src/app/dynamic-form/styles-props.css",
    "content": ".field > label {\n    font-size: 1.1em !important;\n    color: #767676 !important;\n    font-weight: 300\n}\n\n.ui.tabular.menu .active.item {\n    border-top-width: 3px !important;\n    border-top-color: #2185D0 !important;\n}\n\n.ui.segment{\n    border:none;\n}\n\nselect{\n    color: rgba(97, 97, 97, 0.68) !important;\n    height: 3em !important;\n}\n\ninput{\n\n    line-height: 2em;\n    padding: 5px;\n    border-radius: 5px;\n    border-style: solid;\n    border-width: thin;\n    border-color: lightgray;\n    width:100%;\n\n\n}"
  },
  {
    "path": "src/app/error/error-handler.component.ts",
    "content": "import {\n    Component, Input\n} from '@angular/core';\n\nimport {\n    style, trigger, animate, transition\n} from '@angular/animations';\n\nimport {ErrorObject} from './error-model';\n\n\n\n@Component({\n    moduleId: module.id,\n    selector: 'app-error-handler',\n    templateUrl: './view.html',\n    styleUrls: ['./styles-error.css'],\n    animations: [\n\n        trigger('error', [\n            transition(':enter', [\n                style({opacity: 0}),\n                animate('1000ms', style({opacity: 1}))\n            ]),\n            transition(':leave', [\n                style({opacity: 1}),\n                animate('1000ms', style({opacity: 0}))\n            ])\n        ])\n    ]\n})\nexport class ErrorHandlerComponent {\n    @Input() errorObject: ErrorObject;\n    @Input() errorExists: boolean;\n\n    constructor() {\n\n    }\n    public closeMessage() {\n\n        this.errorExists = false;\n    }\n\n}\n\n"
  },
  {
    "path": "src/app/error/error-handler.ts",
    "content": "import {ErrorObject, SolutionObject} from './error-model';\n\n/**\n * Created by jayhamilton on 7/5/17.\n */\nexport class ErrorHandler {\n\n    static getErrorObject(errMsg: any) {\n        return new ErrorObject(\n            errMsg.statusText,\n            'Some description',\n            ErrorHandler.getSolutionList(\n                errMsg.status\n                + ' '\n                + errMsg.statusText),\n            errMsg.resource);\n    }\n\n    /**\n     * todo - fix this error handling logic. Move it to its own class.\n     * @param errMsg\n     * @returns {SolutionObject[]}\n     */\n    static getSolutionList(errMsg: string) {\n\n        console.log(\"ERROR CONDITION:  \" + errMsg )\n\n        const solutionList: SolutionObject[] = [];\n\n        switch (ErrorHandler.getErrorType(errMsg.toLowerCase())) {\n\n            case 'ERR_CERTIFICATE':\n                solutionList.push(new SolutionObject('Check to see if your browser has accepted the certificate', 0, 'http://link1'));\n                break;\n            case 'ERR_CROSS_ORIGIN_RESOURCE_SHARING':\n                solutionList.push(new SolutionObject('Check to see if your browser has accepted the certificate', 0, 'http://link1'));\n                break;\n            case 'ERR_CONNECTION_REFUSED':\n                solutionList.push(new SolutionObject(\n                    'Check to see if the host/service you are attempting to connect to is up.', 0, 'http://link1'));\n                break;\n            case 'ERR_NOT_FOUND':\n                solutionList.push(new SolutionObject(\n                    'Resource not found.', 0, 'http://link1'));\n                break;\n            case 'ERR_CONNECTION_TIMEOUT':\n                solutionList.push(new SolutionObject(\n                    'A timeout occurred. The default timeout on a connection is 60 seconds. ' +\n                    'Check the endpoint to see if you are able to access the ip and port using ping. ' +\n                    'If 60 seconds is to short of a timeout go into configuration and increase it.', 0, 'http://link1'));\n                break;\n            default: {\n                solutionList.push(new SolutionObject(errMsg, 0, 'http://link1'));\n            }\n        }\n\n        return solutionList;\n    }\n\n    static getErrorType(errMsg: string): string {\n\n        if (errMsg.indexOf('trust') > -1) {\n            return 'ERR_CERTIFICATE';\n        }\n        if (errMsg.indexOf('cors') > -1) {\n            return 'ERR_CROSS_ORIGIN_RESOURCE_SHARING';\n        }\n        if (errMsg.indexOf('refuse') > -1) {\n            return 'ERR_CONNECTION_REFUSED';\n        }\n        if (errMsg.indexOf('timeout') > -1) {\n            return 'ERR_CONNECTION_TIMEOUT';\n        }\n        if (errMsg.indexOf('404') > -1) {\n            return 'ERR_NOT_FOUND';\n        }\n        return errMsg;\n    }\n\n    static getWebSocketErrorReason(error: any) {\n\n        let reason = 'There was probably a problem with an attempt to connect to the endpoint!';\n        switch (error.code) {\n            case 1000:\n                reason = 'Normal closure';\n                break;\n            case 1001:\n                reason = 'An endpoint is going away';\n                break;\n            case 1002:\n                reason = 'An endpoint is terminating the connection due to a protocol error.';\n                break;\n            case 1003:\n                reason = 'An endpoint is terminating the connection because it has received a type of data it cannot accept';\n                break;\n            case 1004:\n                reason = 'Reserved. The specific meaning might be defined in the future.';\n                break;\n            case 1005:\n                reason = 'No status code was actually present';\n                break;\n            case 1006:\n                reason = 'The connection was closed abnormally';\n                break;\n            case 1007:\n                reason = 'The endpoint is terminating the connection because a message was received that contained inconsistent data';\n                break;\n            case 1008:\n                reason = 'The endpoint is terminating the connection because it received a message that violates its policy';\n                break;\n            case 1009:\n                reason = 'The endpoint is terminating the connection because a data frame was received that is too large';\n                break;\n            case 1010:\n                reason = 'The client is terminating the connection because it expected the server to negotiate one or more extension, but the server didn\\'t.';\n                break;\n            case 1011:\n                reason = 'The server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.';\n                break;\n            case 1012:\n                reason = 'The server is terminating the connection because it is restarting';\n                break;\n            case 1013:\n                reason = 'The server is terminating the connection due to a temporary condition';\n                break;\n            case 1015:\n                reason = 'The connection was closed due to a failure to perform a TLS handshake';\n                break;\n        }\n        return reason;\n    }\n}\n"
  },
  {
    "path": "src/app/error/error-model.ts",
    "content": "/**\n * Created by jayhamilton on 6/22/17.\n */\nexport class ErrorObject {\n    detail: string;\n    summary: string;\n    solutions: SolutionObject[];\n    resource: string;\n    constructor(detail: string, summary: string, solutions: SolutionObject[], resource: string) {\n        this.detail = detail;\n        this.summary = summary;\n        this.solutions = solutions;\n        this.resource = resource;\n    }\n};\n\nexport class SolutionObject {\n    summary: string;\n    articleId: number;\n    link: string;\n    constructor(summary, articleId, link) {\n        this.summary = summary;\n        this.articleId = articleId;\n        this.link = link;\n    }\n}\n"
  },
  {
    "path": "src/app/error/error.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {ErrorHandlerComponent} from './error-handler.component';\n\n@NgModule({\n    imports: [\n        CommonModule\n    ],\n    declarations: [ErrorHandlerComponent],\n    exports: [ErrorHandlerComponent]\n})\nexport class ErrorHandlerModule {\n}\n"
  },
  {
    "path": "src/app/error/styles-error.css",
    "content": ".error-heading{\n    color:grey !important;\n    text-align: left;\n}\n"
  },
  {
    "path": "src/app/error/view.html",
    "content": "<div [@error]=\"errorExists\" *ngIf=\"errorExists\" class=\"ui bottom attached negative message\">\n    <i class=\"close icon\" (click)=\"closeMessage()\"></i>\n    <div class=\"header\">\n        {{errorObject.summary}}\n    </div>\n    <p>\n        {{errorObject.detail}}\n    </p>\n\n    <p>\n        resource: {{errorObject.resource}}\n    </p>\n\n    <span class=\"error-heading\"> Potential solutions</span>\n    <hr style=\"color:rgba(194,197,200,0.37)\">\n    <div style=\"text-align: left !important\" *ngFor=\"let solution of errorObject.solutions\">\n        <br><span class=\"error-heading\">article:&nbsp;</span> {{solution.link}}\n        <br><span class=\"error-heading\">summary:&nbsp;</span> {{solution.summary}}\n    </div>\n</div>"
  },
  {
    "path": "src/app/facet/capitalize-first-character-pipe.ts",
    "content": "import { Pipe, PipeTransform } from '@angular/core';\n/*\n * Capitalize the first letter of the string\n * Takes a string as a value.\n * Usage:\n *  value | capitalizefirst\n * Example:\n *  // value.name = daniel\n *  {{ value.name | capitalizefirst  }}\n *  fromats to: Daniel\n */\n@Pipe({\n    name: 'capitalizeFirst'\n})\nexport class CapitalizeFirstPipe implements PipeTransform {\n    transform(value: string, args: any[]): string {\n        if (value === null) {\n\n            return 'Not assigned';\n        }\n        return value.charAt(0).toUpperCase() + value.slice(1);\n    }\n}\n"
  },
  {
    "path": "src/app/facet/facet-component.ts",
    "content": "import {Facet} from './facet-model';\nimport {\n    Component, EventEmitter, Input, OnInit, Output\n} from '@angular/core';\n\nimport {\n    style, state, trigger, animate, transition\n} from '@angular/animations';\n\n/**\n * Created by jayhamilton on 7/11/17.\n */\n@Component({\n    moduleId: module.id,\n    selector: 'app-facet',\n    template: `\n\n        <hr style='max-width: 100%; margin-left:0;'>\n        <br>\n        <div class='ui container grid'>\n            <div class='eight wide column' style=\"margin-left: 0 !important;padding-left: 0 !important;\">\n                <h4>{{facet.name}}</h4>\n            </div>\n            <div class='eight wide column'>\n                <div class='ui top right attached label' style='background-color: whitesmoke'>\n                    <i\n                        class='chevron icon' [ngClass]= \"{'up': facetOpen == 'in', 'down': facetOpen=='out'}\"\n                        (click)='toggleAccordion()'\n                        style='color:grey'>\n                    </i>\n                </div>\n            </div>\n        </div>\n        <div [@accordion]='facetOpen'>\n            <table class='ui very basic table' [@accordion2]='facetOpen'>\n                <tbody>\n                <tr *ngFor='let tag of facet.tags'>\n                    <td style=\"width: 35px !important\">\n                        <mat-checkbox (click)='tagSelect(tag.name)'></mat-checkbox>\n                        <!--<input type='checkbox' (click)='tagSelect(tag.name)'>-->\n                    </td>\n                    <td style='color:grey'>{{tag.name}} &nbsp;( {{tag.count}} )</td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n        <br>\n\n    `,\n    styleUrls: ['./styles.css'],\n    animations: [\n\n        trigger('accordion', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('700ms ease-in-out')),\n            transition('out => in', animate('300ms ease-in-out'))\n        ]),\n        trigger('accordion2', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('300ms ease-in-out')),\n            transition('out => in', animate('800ms ease-in-out'))\n        ])\n    ]\n})\nexport class FacetComponent implements OnInit {\n    @Output() tagSelectEvent: EventEmitter<any> = new EventEmitter();\n    @Input() facet: Facet;\n    @Input() openFacet: boolean;\n\n    facetOpen: string;\n\n    constructor() {\n    }\n\n    ngOnInit() {\n        if (this.openFacet) {\n            this.facetOpen = 'in';\n        }else {\n            this.facetOpen = 'out';\n        }\n    }\n\n    toggleAccordion() {\n        this.facetOpen = this.facetOpen === 'out' ? 'in' : 'out';\n\n    }\n\n    tagSelect(tagName) {\n        this.tagSelectEvent.emit(tagName);\n    }\n\n}\n"
  },
  {
    "path": "src/app/facet/facet-model.ts",
    "content": "export class Facet {\n    name: string;\n    tags: Array<Tag>;\n\n    constructor(name: string, tags: Array<Tag>) {\n\n        this.name = name;\n        this.tags = tags;\n    }\n}\n\nexport class Tag {\n    name: string;\n    count: number;\n\n    constructor(name: string) {\n        this.name = name;\n        this.count = 1;\n    }\n}\n"
  },
  {
    "path": "src/app/facet/facet-tag-processor.ts",
    "content": "import {Facet, Tag} from './facet-model';\n\nexport class FacetTagProcessor {\n\n    facet_tags: Array<Facet> = [];\n    objectList: any[];\n\n    constructor(objectList: any[]) {\n        this.objectList = objectList;\n    }\n\n    getFacetTags() {\n\n        const me = this;\n        this.objectList.forEach(function (item) {\n\n            me.formatAndUpdateTagList(item.tags);\n\n        });\n\n        return this.facet_tags;\n    }\n\n    formatAndUpdateTagList(items: any[]) {\n\n        items.forEach(tag => {\n\n            // add the first facet and tag to the facet_tag array\n            if (!this.facet_tags.length) {\n\n                this.createFacetAndAddItToTheFacetTagArray(tag);\n\n            } else {\n\n                let facetExists = false;\n\n                this.facet_tags.forEach(facet => {\n\n                    if (facet.name.toLowerCase() === tag.facet.toLowerCase()) {\n                        facetExists = true;\n                    }\n                });\n\n                if (facetExists) {\n\n                    this.updateFacetWithTag(tag);\n\n                } else {\n\n                    this.createFacetAndAddItToTheFacetTagArray(tag);\n\n                }\n            }\n        });\n    }\n\n    createFacetAndAddItToTheFacetTagArray(tag: any) {\n\n        const _tags: Array<Tag> = [];\n        const _tag: Tag = this.createTag(this.capitalize(tag.name));\n\n        _tags.push(_tag);\n\n        const facet: Facet = new Facet(tag.facet, _tags);\n\n        this.facet_tags.push(facet);\n\n    }\n\n    createTag(tag) {\n\n        return new Tag(tag);\n    }\n\n    updateFacetWithTag(tag: any) {\n\n        // find the facet and then add the tag or update the count\n        this.facet_tags.forEach(facet => {\n\n            if (facet.name.toLowerCase() === tag.facet.toLowerCase()) {\n\n\n                let tagExists = false;\n\n\n                facet.tags.forEach(_tag => {\n\n                    if (_tag.name.toLowerCase() === tag.name.toLowerCase()) {\n\n                        tagExists = true;\n\n                        _tag.count = _tag.count + 1;\n\n                    }\n\n                });\n\n                if (!tagExists) {\n\n                    facet.tags.push(this.createTag(this.capitalize(tag.name)));\n                }\n            }\n\n        });\n    }\n\n    capitalize(value: string) {\n        return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();\n    }\n}\n"
  },
  {
    "path": "src/app/facet/facet.module.ts",
    "content": "import {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {FacetComponent} from './facet-component';\nimport {FilterListComponent} from './filter-list-component';\nimport {FilterTagComponent} from './filter-tag-component';\nimport {CapitalizeFirstPipe} from './capitalize-first-character-pipe';\nimport {MatCheckboxModule} from '@angular/material';\nimport {FormsModule} from '@angular/forms';\nimport {AddGadgetService} from '../add-gadget/service';\n\n@NgModule({\n    imports: [\n        CommonModule,\n        FormsModule,\n        MatCheckboxModule\n    ],\n    declarations: [\n        FacetComponent,\n        FilterListComponent,\n        FilterTagComponent,\n        CapitalizeFirstPipe\n    ],\n    providers: [\n        AddGadgetService\n    ],\n    exports: [\n        FacetComponent,\n        FilterListComponent,\n        FilterTagComponent,\n        CapitalizeFirstPipe\n    ]\n})\nexport class FacetModule {\n}\n"
  },
  {
    "path": "src/app/facet/filter-list-component.ts",
    "content": "import {Component, EventEmitter, Input, Output} from '@angular/core';\nimport {AddGadgetService} from '../add-gadget/service';\nimport {Facet, Tag} from './facet-model';\n\n/**\n * Created by jayhamilton on 6/27/17.\n */\n@Component({\n    moduleId: module.id,\n    selector: 'app-filter-list',\n    template: `\n        <br>\n        <div *ngFor='let facet of facet_tags ;let i = index'>\n\n            <app-facet [facet]='facet' (tagSelectEvent)='tagSelect($event)' [openFacet]='i < 2'></app-facet>\n\n        </div>\n    `,\n    styleUrls: ['./styles.css']\n})\nexport class FilterListComponent {\n    @Output() tagSelectEvent: EventEmitter<any> = new EventEmitter();\n    @Input() facet_tags: Array<Facet>;\n\n    tagSelect(tagName) {\n\n        this.tagSelectEvent.emit(tagName);\n\n    }\n}\n"
  },
  {
    "path": "src/app/facet/filter-tag-component.ts",
    "content": "import { Component, EventEmitter, Output} from '@angular/core';\n\nimport {\n    style, trigger, animate, transition\n} from '@angular/animations';\n/**\n * Created by jayhamilton on 6/27/17.\n */\n@Component({\n    moduleId: module.id,\n    selector: 'app-filter-tag',\n    template: `\n        <div class='ui basic segment' style='background-color:white; min-height: 4.5em; border-radius:5px'>\n            <div class='ui large circular labels'>\n               <a class='ui label' [@showHideAnimation] *ngFor='let tag of filterList'>\n                    {{tag}}\n                </a>\n            </div>\n        </div>\n    `,\n    styleUrls: ['../gadgets/_common/styles-gadget.css'],\n    animations: [\n        trigger(\n            'showHideAnimation',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(750, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(750, style({opacity: 0}))\n                ])\n            ])\n    ]\n\n})\nexport class FilterTagComponent {\n\n    @Output() updateFilterListEvent = new EventEmitter<any>();\n\n    filterList: Array<string> = [];\n\n    constructor() {\n    }\n\n    updateFilterList(filter) {\n\n        filter = filter.toLocaleLowerCase();\n\n        const index: number = this.filterList.indexOf(filter);\n        if (index !== -1) {\n            this.filterList.splice(index, 1);\n        } else {\n            this.filterList.push(filter);\n        }\n\n        this.updateFilterListEvent.emit(this.filterList);\n\n    }\n}\n"
  },
  {
    "path": "src/app/facet/styles.css",
    "content": ".ui.avatar.image {\n    width: 4.4em !important;\n    height: 4em !important\n}\n\nhr {\n    height: 2px !important;\n    color: rgba(110, 110, 110, 0.1) !important;\n    background: rgba(110, 110, 110, 0.1) !important;\n    font-size: 0;\n    border: 0;\n\n}\n\n.ui.input input:focus, .ui.input.focus input {\n    border-color: #e9e9e9 !important;\n}\n\nh3, h4 {\n    color: rgba(66, 66, 66, .74) !important;\n    font-weight: 400 !important;\n    font-size:.85em;\n}\n\n.ui.basic.segment {\n    border-radius: 5px !important;\n}\n\n.segment {\n    border-radius: 5px !important;\n}\n\n.ui.table tr td {\n    border-top: none !important;\n}\n\n.ui.table td {\n    padding: .3em !important;\n    font-size: .8em;\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/base-chart-models/bar.model.ts",
    "content": "import {Series} from './series.model';\n\nexport abstract class Bar {\n\n    public name: string;\n    public series: Array<Series>;\n\n\n    constructor(name: string, series: Array<Series>) {\n        this.name = name;\n        this.series = series;\n    }\n\n}"
  },
  {
    "path": "src/app/gadgets/_common/base-chart-models/series.model.ts",
    "content": "export class Series {\n\n    public name: string;\n    public value: number;\n\n    constructor(name: string, value: number) {\n        this.name = name;\n        this.value = value;\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/gadget-base.ts",
    "content": "import {ErrorObject} from '../../error/error-model';\nimport {EndPoint} from '../../configuration/tab-endpoint/endpoint.model';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from './gadget-property.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {AfterViewInit, ChangeDetectorRef, OnDestroy, OnInit, ViewChild} from '@angular/core';\nimport {DynamicFormComponent} from '../../dynamic-form/dynamic-form.component';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n/**\n * Created by jayhamilton on 6/22/17.\n */\n\nexport abstract class GadgetBase implements IGadget, OnDestroy, OnInit, AfterViewInit {\n    @ViewChild(DynamicFormComponent) propertyPageForm: DynamicFormComponent;\n    title: string;\n    instanceId: number;\n    config: any;\n    gadgetTags: Array<any>;\n\n    /**\n     * Used to determine when to show the controls that appear in the gadgets\n     * heading area. This is set by the mouseover/mouseout events.\n     * @type {boolean}\n     */\n    showControls = false;\n\n    /**\n     * determines whether to show the gadgets property page\n     * @type {boolean}\n     */\n    inConfig = false;\n\n    /**\n     * Determines if a gadget is runnning or not\n     * @type {boolean}\n     */\n    inRun = false;\n\n    /**\n     * When a gadget is manually put into run mode this property will be used to\n     * display a spinning icon and will be enabled between intiating an operation (run or stop)\n     * to the operation is enabled\n     * @type {boolean}\n     */\n    actionInitiated = false;\n\n    /**\n     * Gadgets that are of type realtime have a run/stop set of controls.\n     * Those gadgets should set this property to true. This property's visibility\n     * will also be controlled by whether the gadget's configuration form is valid.\n     * @type {boolean}\n     */\n    showOperationControls = false;\n    /**\n     * This property is used to simply allow the gadget to not show any run/stop controls.\n     * This is needed because the showOperationControls does something similar but not exactly the same.\n     * The showOperationControls property allows the gadgetBase to determine if the run control, if the gadget\n     * uses it, to be displayed when the gadget has a valid configuration.\n     *\n     * Default: true - Gadgets without a need for run/stop control should override this value.\n     * @type {boolean}\n     */\n    gadgetHasOperationControls = true;\n\n    /**\n     * Most gadgets need configuration so gadgets that don't can override this property\n     * @type {boolean}\n     */\n    showConfigurationControl = true;\n\n    // internally controls dynamic form properties\n    propertyPages: any[] = [];\n\n    endpointObject: EndPoint;\n\n    errorObject: ErrorObject;\n    errorExists = false;\n    globalOptions:any;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService) {\n\n        this._optionsService.listenForGlobalOptionsChanges().subscribe(options=>{\n\n            /**\n             * This is called when there is a change to the options tab within the configuration modal.\n             * The following method needs to also be called when the gadget is initially instantiated.\n             * When the gadget is instantiated the option values need to come from the persistent store.\n             */\n\n            this.updateGadgetWithGlobalOptions(options);\n        });\n\n        this.updateGadgetWithGlobalOptions(this._optionsService.getBoardOptions())\n    }\n\n    public ngOnInit() {\n       this.toggleConfigMode();\n       this.changeDetectionRef.detectChanges();\n    }\n\n    public ngAfterViewInit() {\n\n\n        if (this.propertyPageForm) {\n\n            if (this.propertyPageForm.isPropertyPageValid) {\n                this.toggleConfigMode();\n                this.changeDetectionRef.detectChanges();\n\n                this.showOperationControls = true;\n                this.changeDetectionRef.detectChanges();\n            } else {\n                this.showOperationControls = false;\n                this.changeDetectionRef.detectChanges();\n            }\n        }\n        this.preRun();\n    }\n\n    public initializeState() {\n\n    }\n\n    public toggleConfigMode() {\n\n        if (!this.inConfig) {\n\n            this.initializeProperties();\n        }\n        this.inConfig = !this.inConfig;\n    }\n\n    public initializeProperties() {\n\n        if (this.propertyPages.length === 0 && this.config.propertyPages) {\n            this._propertyService.setPropertyPagesAndProperties(this.config.propertyPages, this.propertyPages);\n        }\n    }\n\n    public abstract run(): void\n\n    public abstract stop(): void\n\n    public abstract updateProperties(updatedProperties: any): void\n\n    public abstract updateData(data: any[]): void\n\n    public abstract preRun(): void\n\n    public handleError(error: ErrorObject) {\n\n\n        this.inRun = false;\n        this.actionInitiated = false;\n        this.errorExists = true;\n        this.errorObject = error;\n\n    }\n\n    public initializeRunState(forceRunState: boolean) {\n\n        this.errorExists = false;\n        this.actionInitiated = true;\n        this.inConfig = false;\n        if (forceRunState) {\n            this.setInRunState();\n        }\n    }\n\n    public setInRunState() {\n\n        this.inRun = true;\n        this.actionInitiated = false;\n    }\n\n    public setStopState(longRunningStopAction: boolean) {\n        /**\n         *  If the gadget indicates longRunningStopAction then the gadget has to set this value to\n         *  false once the operation is complete\n         */\n        this.actionInitiated = longRunningStopAction;\n        this.inRun = false;\n\n    }\n\n    public remove() {\n        this._gadgetInstanceService.removeInstance(this.instanceId);\n    }\n\n    public showGadgetControls(enable: boolean) {\n        this.showControls = enable;\n    }\n\n    /**\n     * called from cell.component after the gadget is created during runtime\n     * intanceId, config, title and endpoint are common to all gadgets. Once the gadgets are configured\n     * we give them an opportunity to perform an action during the preRun() method. For example,\n     * the statistic gadget uses preRun() to make a single call to the endpoint to update its display.\n     * */\n    public configureGadget(instanceId: number, config: any, tags: Array<any>) {\n\n        this.instanceId = instanceId;\n        this.config = config;\n        this.gadgetTags = tags.slice();\n\n        this.setTitle(this.getPropFromPropertyPages('title'));\n        this.setEndPoint(this.getPropFromPropertyPages('endpoint'));\n\n        /**\n         *  Todo - remove this prerun call and refactor remaining code. Prerun was called twice and had an impact on the barchart api calls.\n         *  API calls continued after route changes which is undesirable. See ngAfterViewInit where it is also called from.\n         */\n        //this.preRun();\n\n    }\n\n    protected setEndPoint(endpoint: string) {\n\n        this._endPointService.getEndPoints().subscribe(data => {\n\n            if (data['endPoint']) {\n                data['endPoint'].forEach(item => {\n                    if (item.name === endpoint) {\n                        this.endpointObject = item;\n                    }\n                });\n            }\n        });\n    }\n\n    protected getEndPoint() {\n        return this.endpointObject;\n    }\n\n    protected setTitle(title: string) {\n        this.title = title;\n    }\n\n    protected getPropFromPropertyPages(prop: string) {\n\n        for (let x = 0; x < this.config.propertyPages.length; x++) {\n\n            for (let i = 0; i < this.config.propertyPages[x].properties.length; i++) {\n\n                if (this.config.propertyPages[x].properties[i].key === prop) {\n                    return this.config.propertyPages[x].properties[i].value;\n                }\n            }\n\n        }\n        return 'Unknown';\n    }\n\n    public ngOnDestroy() {\n\n    }\n\n    public updateGadgetWithGlobalOptions(options:any){\n\n\n        this.globalOptions = Object.assign({},options);\n\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/gadget-config-model.ts",
    "content": "import {PropertyBase} from '../../dynamic-form/property-base';\n\n/**\n * Created by jayhamilton on 6/15/17.\n */\n\nexport class GadgetConfigModel {\n    propertyPages: PropertyPage[] = [];\n\n    constructor(config: any) {\n\n        config.propertyPages.forEach((page) => {\n\n            const props: PropertyBase<any>[] = [];\n\n            page.properties.forEach((prop) => {\n\n                switch (prop.controlType) {\n                    case 'textbox':\n                    case 'dropdown':\n                    case 'dynamicdropdown':\n                        props.push(new PropertyBase<string>(prop));\n                        break;\n                    case 'checkbox':\n                        props.push(new PropertyBase<boolean>(prop));\n                        break;\n                    case 'hidden':\n                        props.push(new PropertyBase<number>(prop));\n                        break;\n                    default:\n                        props.push(new PropertyBase<string>(prop));\n                        break;\n                }\n            });\n\n            this.propertyPages.push(new PropertyPage(page.displayName, page.groupId, page.position, props));\n        });\n    }\n}\n\nclass PropertyPage {\n    displayName: string;\n    groupId: string;\n    position: number;\n    properties: PropertyBase<any>[];\n\n    constructor(displayName: string, groupId: string, position: number, properties: PropertyBase<any>[]) {\n        this.displayName = displayName;\n        this.groupId = groupId;\n        this.position = position;\n        this.properties = properties;\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/gadget-header-component.ts",
    "content": "/**\n * Created by jayhamilton on 2/28/17.\n */\nimport {Component, Input, Output, EventEmitter} from '@angular/core';\n/**\n * Created by jayhamilton on 2/26/17.\n */\n\n@Component({\n    moduleId: module.id,\n    selector: 'app-gadget-header',\n    templateUrl: './gadget-header.html',\n    styleUrls: ['./styles-gadget.css']\n})\nexport class GadgetHeaderComponent {\n    @Input() title: string;\n    @Input() showControls: boolean;\n    @Input() inRun: boolean;\n    @Input() inConfig: boolean;\n    @Input() actionInitiated: boolean;\n    @Input() showOperationControls: boolean;\n    @Input() showConfigurationControl: boolean;\n    @Input() gadgetHasOperationControls: boolean;\n    @Input() globalOptions:any;\n    @Output() removeEvent: EventEmitter<any> = new EventEmitter();\n    @Output() toggleConfigModeEvent: EventEmitter<any> = new EventEmitter();\n    @Output() runEvent: EventEmitter<any> = new EventEmitter();\n    @Output() stopEvent: EventEmitter<any> = new EventEmitter();\n    @Output() helpEvent: EventEmitter<any> = new EventEmitter();\n\n\n    remove() {\n        this.removeEvent.emit();\n    }\n\n    toggleConfigMode() {\n        this.toggleConfigModeEvent.emit();\n    }\n\n    run() {\n\n        this.runEvent.emit();\n\n    }\n\n    stop() {\n\n        this.stopEvent.emit();\n    }\n\n    help(){\n        this.helpEvent.emit();\n    }\n\n}"
  },
  {
    "path": "src/app/gadgets/_common/gadget-header.html",
    "content": "<div class=\"ui top attached label\">\n\n    <button class=\"compact ui button right floated\"\n            *ngIf=\"showControls || globalOptions.enableHover\" (click)=\"remove()\">\n        <i class=\"trash icon\" style=\"margin-right:0 !important\"></i>\n    </button>\n    <button class=\"compact ui button right floated\"\n            *ngIf=\"showControls || globalOptions.enableHover && showConfigurationControl\" (click)=\"toggleConfigMode()\">\n        <i class=\"setting  icon\" style=\"margin-right:0 !important\"></i>\n    </button>\n    <button class=\"compact ui button right floated\"\n            *ngIf=\"showControls || globalOptions.enableHover\" (click)=\"help()\">\n        <i class=\"info icon\" style=\"margin-right:0 !important\" ></i>\n    </button>\n\n    <app-gadget-operation-control *ngIf=\"showControls || globalOptions.enableHover\"\n                              [inRun]=\"inRun\"\n                              [inConfig]=\"inConfig\"\n                              [actionInitiated]=\"actionInitiated\"\n                              [showOperationControls]=\"showOperationControls\"\n                              [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n                              (runEvent)=\"run()\"\n                              (stopEvent)=\"stop()\">\n\n    </app-gadget-operation-control>\n\n    <div class=\"ui top left floated label ct-title\">{{title}}</div>\n</div>\n<div class=\"spacer\"></div>\n    "
  },
  {
    "path": "src/app/gadgets/_common/gadget-operation-control-component.ts",
    "content": "import {Component, EventEmitter, Input, Output} from '@angular/core';\n\n/**\n * Created by jayhamilton on 6/29/17.\n */\n\n@Component({\n    moduleId: module.id,\n    selector: 'app-gadget-operation-control',\n    template: `\n\n        <button class=\"compact ui button right floated\"\n                *ngIf=\"!inRun && !actionInitiated && showOperationControls && gadgetHasOperationControls\"\n                (click)=\"run()\"><i class=\"green play icon\" style=\"margin-right:0 !important\"></i>\n        </button>\n\n        <button class=\"compact ui button right floated\"\n                *ngIf=\"!inRun && \n        actionInitiated && \n        showOperationControls && \n        gadgetHasOperationControls\">\n            <i class=\"black spinner loading icon\" style=\"margin-right:0 !important\"></i>\n        </button>\n\n        <button class=\"compact ui button right floated\"\n                *ngIf=\"inRun && !actionInitiated && showOperationControls && gadgetHasOperationControls\"\n                (click)=\"stop()\"><i class=\"red stop icon\" style=\"margin-right:0 !important\"></i>\n        </button>\n    `,\n})\nexport class GadgetOperationComponent {\n    @Output() runEvent: EventEmitter<any> = new EventEmitter();\n    @Output() stopEvent: EventEmitter<any> = new EventEmitter();\n\n    @Input() inRun: boolean;\n    @Input() actionInitiated: boolean;\n    @Input() inConfig: boolean;\n    @Input() showOperationControls: boolean;\n    @Input() gadgetHasOperationControls: boolean;\n\n\n    run() {\n        this.runEvent.emit();\n    }\n\n    stop() {\n        this.stopEvent.emit();\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/gadget-property.service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {DropdownProperty} from '../../dynamic-form/property-dropdown';\nimport {PropertyBase} from '../../dynamic-form/property-base';\nimport {TextboxProperty} from '../../dynamic-form/property-textbox';\nimport {HiddenProperty} from '../../dynamic-form/property-hidden';\nimport {CheckboxProperty} from '../../dynamic-form/property-checkbox';\nimport {DynamicDropdownProperty} from '../../dynamic-form/property-dynamicdropdown';\nimport {NumberProperty} from '../../dynamic-form/property-number';\n\n@Injectable()\nexport class GadgetPropertyService {\n\n    constructor() {\n    }\n\n    setPropertiesAndValues(defaultProperties: any[], properties: PropertyBase<any>[]) {\n        let ctrl: PropertyBase<any>;\n\n        properties.length = 0;\n\n        defaultProperties.forEach(function (property) {\n\n            if (property.controlType === 'dropdown') {\n                ctrl = new DropdownProperty(property);\n                properties.push(ctrl);\n            } else if (property.controlType === 'textbox') {\n                ctrl = new TextboxProperty(property);\n                properties.push(ctrl);\n            } else if (property.controlType === 'checkbox') {\n                ctrl = new CheckboxProperty(property);\n                properties.push(ctrl);\n            } else if (property.controlType === 'hidden') {\n                ctrl = new HiddenProperty(property);\n                properties.push(ctrl);\n            } else if (property.controlType === 'number') {\n                ctrl = new NumberProperty(property);\n                properties.push(ctrl);\n            } else if (property.controlType === 'dynamicdropdown') {\n                ctrl = new DynamicDropdownProperty(property);\n                properties.push(ctrl);\n\n            }\n        });\n\n        properties.sort((a, b) => a.order - b.order);\n    }\n\n    setPropertyPagesAndProperties(defaultPropertyPages: any[], propertyPages: any[]) {\n\n        const me = this;\n\n        // for each defaultPropertyPage object, get the properties\n        defaultPropertyPages.forEach(function (propertyPage) {\n\n            const newPropertyPage: any = {};\n\n            for (const property in propertyPage) {\n\n                if (propertyPage.hasOwnProperty(property)) {\n\n                    if (property !== 'properties') {\n\n                        newPropertyPage[property] = propertyPage[property];\n\n                    } else {\n\n                        const properties: PropertyBase<any>[] = [];\n                        me.setPropertiesAndValues(propertyPage.properties, properties);\n                        newPropertyPage['properties'] = properties;\n                    }\n                }\n            }\n\n            propertyPages.push(newPropertyPage);\n\n        });\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/gadget-shared.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {GadgetHeaderComponent} from './gadget-header-component';\nimport {GadgetOperationComponent} from './gadget-operation-control-component';\nimport {HelpModalComponent} from './help-modal-component';\nimport {VisDrillDownComponent} from './vis-drill-down-component';\nimport {DndModule} from 'ng2-dnd';\nimport {MatProgressBarModule} from '@angular/material';\n\n@NgModule({\n    imports: [\n        CommonModule,\n        DndModule.forRoot(),\n        MatProgressBarModule,\n    ],\n    declarations: [\n\n        GadgetHeaderComponent,\n        GadgetOperationComponent,\n        HelpModalComponent,\n        VisDrillDownComponent\n\n    ],\n    exports: [\n        GadgetHeaderComponent,\n        GadgetOperationComponent,\n        HelpModalComponent,\n        VisDrillDownComponent\n    ]\n})\nexport class GadgetSharedModule {\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/help-modal-component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    ViewChild, ElementRef, AfterViewInit, Component, Input\n} from '@angular/core';\n\ndeclare var jQuery: any;\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-help-modal',\n    moduleId: module.id,\n    templateUrl: './help-modal.html',\n\n})\nexport class HelpModalComponent implements AfterViewInit {\n\n    @Input() topic: any;\n\n    modalicon: string;\n    modalheader: string;\n    modalconfig: string;\n\n    @ViewChild('helpmodal_tag') helpmodalaRef: ElementRef;\n    configModal: any;\n\n\n    constructor() {\n    }\n\n\n    showMessageModal(icon: string, header: string, message: string) {\n        this.modalicon = icon;\n        this.modalheader = header;\n        this.modalconfig = message;\n        this.configModal.modal('show');\n\n    }\n\n\n    hideMessageModal() {\n        this.modalicon = '';\n        this.modalheader = '';\n        this.modalconfig = '';\n        this.configModal.modal('hide');\n    }\n\n\n    ngAfterViewInit() {\n        this.configModal = jQuery(this.helpmodalaRef.nativeElement);\n        this.configModal.modal('hide');\n    }\n\n    showHelp() {\n\n        this.showMessageModal(null, 'Help', 'Get me out of here!');\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/help-modal.html",
    "content": "<div class=\"ui long modal\" #helpmodal_tag>\n    <div class=\"header\">\n        Help\n    </div>\n\n    <div class=\"ui basic segment\">\n        <br>\n        <br>\n        <p></p>\n\n        <!--\n            <h3 style=\"font-weight:600 !important\">{{topic.heading}}</h3>\n            <div *ngFor=\"let detail of topic.details\" class=\"ui segment\">\n                <h4 style=\"font-weight:500 !important\">{{detail.category}}</h4>\n\n                <div class=\"ui divided items\">\n                    <div class=\"item\" *ngFor=\"let article of detail.articles\">\n                        <div class=\"content\">\n                            <h5>{{article.headline}}</h5>\n                            <div class=\"description\">\n                                <p>{{article.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n-->\n        <br><br>\n    </div>\n    <div class=\"actions\">\n        <div class=\"ui approve button\">Close</div>\n    </div>\n</div>"
  },
  {
    "path": "src/app/gadgets/_common/igadget.ts",
    "content": "/**\n * Created by jayhamilton on 2/25/17.\n */\ninterface IGadget {\n\n    run();\n\n    stop();\n\n    toggleConfigMode();\n\n    initializeProperties();\n\n    updateProperties(updatedProperties: any);\n\n    updateData(data: any[]);\n\n    handleError(error: any);\n\n    remove();\n\n    showGadgetControls(enable: boolean);\n\n    configureGadget(instanceId: number, config: any, tags: Array<any>);\n\n    updateGadgetWithGlobalOptions(options:any);\n\n\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/styles-gadget.css",
    "content": ".gadget {\n    margin-bottom: 15px !important;\n    min-height: inherit !important;\n    font-family: 'Helvetica Neue', Helvetica, 'Open Sans', Arial, 'Lucida Grande', sans-serif;\n    color: grey;\n}\n\n:host /deep/ div:not(.proppages) {\n    margin-left: auto;\n    margin-right: auto;\n    display: block !important\n}\n\n.ui.form .field > label {\n    font-family: 'Helvetica Neue', Helvetica, 'Open Sans', Arial, 'Lucida Grande', sans-serif;\n    font-size: 1.3em !important;\n    font-weight: 300;\n    color: grey;\n}\n\n#bt {\n    text-align: center !important\n}\n\ninput {\n    padding: 5px;\n    border: none !important;\n    width: 75% !important;\n    font-weight: 300 !important;\n    font-family: 'Helvetica Neue', Helvetica, 'Open Sans', Arial, 'Lucida Grande', sans-serif;\n    font-size: 1.3em !important;\n    outline: none !important;\n}\n\n.ct-title {\n    color: #585858 !important;\n    font-size: 1.5em !important;\n    font-family: 'Helvetica Neue', Helvetica, 'Open Sans', Arial, 'Lucida Grande', sans-serif;\n    text-align: left !important;\n    font-weight: 500 !important;\n}\n\n.ui.top.left.floated.label, .ui.top.attached.label {\n    background-color: white;\n}\n\nhr {\n    font-weight: 300 !important;\n    height: 1px;\n    border-style: solid;\n    color: black;\n\n}\n\n.ui[class*=\"top attached\"].label:before {\n    content: \"\";\n    position: absolute;\n    left: 2%;\n    bottom: 5px;\n    height: 1px;\n    width: 95%; /* or 100px */\n    border-bottom: 0px solid #d0d3d6;\n}\n\n.spacer {\n    height: 2em;\n}\n\n.ui.items > .item > .content > .description {\n    color: darkgray !important;\n}\n\n.suggestions > li {\n\n    background-color: white !important;\n\n}\n\ntd {\n    font-family: 'Helvetica Neue', Helvetica, 'Open Sans', Arial, 'Lucida Grande', sans-serif;\n    color: grey;\n}\n\nth {\n    font-family: 'Helvetica Neue', Helvetica, 'Open Sans', Arial, 'Lucida Grande', sans-serif;\n    color: #336699;\n}\n\n.example-full-width {\n    width: 100%;\n}\n\nh4 {\n    font-weight: 400;\n}\n\n.ui.segment {\n\n    border: none;\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/vis-drill-down-component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    ViewChild, ElementRef, AfterViewInit, Component\n} from '@angular/core';\n\nimport {\n    style, state, trigger, animate, transition\n} from '@angular/animations';\n\nimport {Facet} from '../../facet/facet-model';\n\n\ndeclare var jQuery: any;\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-vis-drill-down-modal',\n    moduleId: module.id,\n    templateUrl: './vis-drill-down.html',\n    animations: [\n\n        trigger('contentSwitch', [\n            state('inactive', style({\n                opacity: 0\n            })),\n            state('active', style({\n                opacity: 1\n            })),\n            transition('inactive => active', animate('750ms ease-in')),\n            transition('active => inactive', animate('750ms ease-out'))\n        ]),\n        trigger('tabSwitch', [\n            state('inactive', style({\n                opacity: .75\n            })),\n            state('active', style({\n                opacity: 1\n            })),\n            transition('inactive => active', animate('750ms ease-in')),\n            transition('active => inactive', animate('750ms ease-out'))\n        ])\n    ]\n\n\n})\nexport class VisDrillDownComponent implements AfterViewInit {\n\n    modalicon: string;\n    modalheader: string;\n    modalconfig: string;\n    vms: any[];\n    objectList: any[] = [];\n    objectTitleList: string[] = [];\n    placeHolderText = 'Begin typing vm name';\n    layoutColumnOneWidth = 'six';\n    layoutColumnTwoWidth = 'ten';\n    facetTags: Array<Facet> = [];\n\n    @ViewChild('vismodal_tag') vismodalaRef: ElementRef;\n    configModal: any;\n\n\n    constructor() {\n\n    }\n\n    showMessageModal(icon: string, header: string, message: string) {\n        this.modalicon = icon;\n        this.modalheader = header;\n        this.modalconfig = message;\n        this.configModal.modal('show');\n\n    }\n\n\n    hideMessageModal() {\n        this.modalicon = '';\n        this.modalheader = '';\n        this.modalconfig = '';\n        this.configModal.modal('hide');\n    }\n\n\n    ngAfterViewInit() {\n        this.configModal = jQuery(this.vismodalaRef.nativeElement);\n        this.configModal.modal('hide');\n    }\n\n    showDrillDownDetail($event) {\n\n        const data: string = JSON.stringify($event, null, 4);\n        this.showMessageModal(null, 'Detail', data);\n\n\n    }\n\n    showDetail($event) {\n\n        const data: string = JSON.stringify($event, null, 4);\n        this.showMessageModal(null, 'Detail', data);\n\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/_common/vis-drill-down.html",
    "content": "<div class=\"ui long modal\" #vismodal_tag>\n    <div class=\"header\">\n        <h2>{{modalheader}}</h2>\n    </div>\n\n\n    <div class=\"content\">\n\n        {{modalconfig}}\n\n    </div>\n\n\n    <div class=\"actions\">\n        <div class=\"ui approve button\">Close</div>\n    </div>\n</div>"
  },
  {
    "path": "src/app/gadgets/barchart/barchart-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, ElementRef, ViewChild} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {BarChartService} from './service';\nimport {Router} from '@angular/router';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\nimport {startWith, switchMap} from \"rxjs/operators\";\nimport {interval} from \"rxjs\";\nimport {ConfigurationService} from \"../../services/configuration.service\";\n\ndeclare var jQuery: any;\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class BarChartGadgetComponent extends GadgetBase {\n\n    @ViewChild('chartOptionsSideBar_tag') chartOptionsSideBarRef: ElementRef;\n    chartOptionsSideBar: any;\n\n    // chart options\n    showXAxis: boolean;\n    showYAxis: boolean;\n    gradient: boolean;\n    showLegend: boolean;\n    showXAxisLabel: boolean;\n    showYAxisLabel: boolean;\n    barChartType: string;\n    showDataLabel: boolean;\n    yAxisLabel: string;\n    xAxisLabel: string;\n    view: any[];\n    colorScheme: any = {\n        domain: ['#0AFF16', '#B2303B'] //todo - control color from property page\n    };\n    //////////////////\n\n    data: any[] = [];\n    subscription: any;\n    state: string;\n\n    RUN_STATE = 'run';\n    STOP_STATE = 'stop';\n    POLL_INTERVAL = 15000;\n\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _barChartService: BarChartService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService,\n                private _configService: ConfigurationService,\n                private _route: Router\n    ) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun() {\n\n        /**\n         * the base class initializes the common property gadgets. Prerun gives\n         * us a chance to initialize any of the gadgets unique properties.\n         */\n        this.initializeTheRemainderOfTheProperties();\n\n        if (this.getPropFromPropertyPages('state') == this.RUN_STATE) {\n            this.run();\n        }\n    }\n\n    initializeTheRemainderOfTheProperties() {\n\n        this.gradient = this.getPropFromPropertyPages('gradient');\n        this.showXAxis = this.getPropFromPropertyPages('showXAxis');\n        this.showYAxis = this.getPropFromPropertyPages('showYAxis');\n        this.showLegend = this.getPropFromPropertyPages('showLegend');\n        this.showXAxisLabel = this.getPropFromPropertyPages('showXAxisLabel');\n        this.showYAxisLabel = this.getPropFromPropertyPages('showYAxisLabel');\n        this.barChartType = this.getPropFromPropertyPages('barChartType');\n        this.showDataLabel = this.getPropFromPropertyPages('showDataLabel');\n        this.yAxisLabel = this.getPropFromPropertyPages('yAxisLabel');\n        this.xAxisLabel = this.getPropFromPropertyPages('xAxisLabel');\n\n    }\n\n\n    public run() {\n\n        this.clearChartData();\n        this.initializeRunState(true);\n        this.updateData(null);\n        this.saveState(this.RUN_STATE);\n\n    }\n\n    clearChartData() {\n        this.data = [];\n    }\n\n\n    public stop() {\n\n        this.stopWithoutStateSave();\n        this.saveState(this.STOP_STATE);\n    }\n\n    /**\n     * The state is being saved to allow the board to load with the last state. Also, when the gadget is moved\n     * within the board we need to carry the gadget's state along.\n     * @param state\n     */\n    public saveState(state: string) {\n\n        this.updateProperties('{\\\"state\\\":\\\"' + state + '\\\"}');\n        this.persistTheChangeInInternalState();\n\n    }\n\n    /**\n     * When the gadget is destroyed (see ngOnDestroy) there is no need to\n     * save the state. We just want to stop any API calls.\n     */\n    public stopWithoutStateSave() {\n        if (this.subscription) {\n            this.subscription.unsubscribe();\n        }\n        const data = [];\n        Object.assign(this, {data});\n        this.setStopState(false);\n\n    }\n\n    public updateData(someData: any[]) {\n        this.data.length = 0;\n\n        /**\n         * poll every 15 seconds\n         * todo - change this to a websocket\n         */\n        this.subscription = interval(this.POLL_INTERVAL).pipe(\n            startWith(0), switchMap(() => this._barChartService.getData(this.endpointObject.address)))\n            .subscribe(data => {\n\n                    Object.assign(this, {data});\n                },\n                error => this.handleError(error));\n    }\n\n    public drillDown(data) {\n\n        this.stopWithoutStateSave();\n\n        this._route.navigate(['/detail'], {\n            queryParams:\n                {\n                    chartType:\"bar\",\n                    chartSeries: data.series,\n                    chartMetric: data.name,\n                    endPointName: this.endpointObject.name\n                }\n        });\n    }\n\n\n    private setInternalProperties(updatedPropsObject: any) {\n\n        this.state = updatedPropsObject.state;\n\n        if (updatedPropsObject.title != undefined) {\n\n            this.title = updatedPropsObject.title;\n            this.showXAxis = updatedPropsObject.showXAxis;\n            this.showYAxis = updatedPropsObject.showYAxis;\n            this.gradient = updatedPropsObject.gradient;\n            this.showLegend = updatedPropsObject.showLegend;\n            this.showXAxisLabel = updatedPropsObject.showXAxisLabel;\n            this.showYAxisLabel = updatedPropsObject.showYAxisLabel;\n            this.barChartType = updatedPropsObject.barChartType;\n            this.showDataLabel = updatedPropsObject.showDataLabel;\n            this.xAxisLabel = updatedPropsObject.xAxisLabel;\n            this.yAxisLabel = updatedPropsObject.yAxisLabel;\n            this.setEndPoint(updatedPropsObject.endpoint);\n            this.showOperationControls = true;\n        }\n    }\n\n    /**\n     * todo\n     *  This is called from the dynamic property page form or when the internal running state changes\n     *  A similar operation exists on the procmman-config-service\n     *  whenever the property page form is saved, the in memory board model\n     *  is updated as well as the gadget instance properties\n     *  which is what the code below does. This can be eliminated with code added to the\n     *  config service or the property page service.\n     *\n     * **/\n    public updateProperties(updatedProperties: any) {\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n\n        /**\n         * update this tools property pages\n         */\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        /**\n         * update the tools internal state\n         */\n        this.setInternalProperties(updatedPropsObject);\n\n    }\n\n    public ngOnDestroy() {\n\n        this.stopWithoutStateSave();\n    }\n\n\n    /**\n     * todo - need to improve how internal state is saved to persistant store\n     */\n    private persistTheChangeInInternalState() {\n        let payLoad =\n            \"{\\\"instanceId\\\":\" + this.instanceId\n            + \",\\\"title\\\":\\\"\" + this.title\n            + \"\\\",\\\"state\\\":\\\"\" + this.state\n            + \"\\\",\\\"endpoint\\\":\\\"\" + this.endpointObject.name\n            + \"\\\",\\\"gradient\\\":\" + this.gradient\n            + \",\\\"showXAxis\\\":\" + this.showXAxis\n            + \",\\\"showYAxis\\\":\" + this.showYAxis\n            + \",\\\"showLegend\\\":\" + this.showLegend\n            + \",\\\"showXAxisLabel\\\":\" + this.showXAxisLabel\n            + \",\\\"showYAxisLabel\\\":\" + this.showYAxisLabel\n            + \",\\\"showDataLabel\\\":\" + this.showDataLabel\n            + \",\\\"barChartType\\\":\\\"\" + this.barChartType\n            + \"\\\",\\\"yAxisLabel\\\":\\\"\" + this.yAxisLabel\n            + \"\\\",\\\"xAxisLabel\\\":\\\"\" + this.xAxisLabel\n            + \"\\\"}\";\n\n\n        this._configService.notifyGadgetOnPropertyChange(payLoad, this.instanceId);\n\n    }\n\n    toggleChartProperties() {\n\n        if (this.globalOptions.displayGadgetOptionsInSideBar == false) {\n            this.toggleConfigMode();\n            return;\n        }\n        this.chartOptionsSideBar = jQuery(this.chartOptionsSideBarRef.nativeElement);\n        this.chartOptionsSideBar.sidebar('setting', 'transition', 'overlay');\n        this.chartOptionsSideBar.sidebar('toggle');\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/barchart/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\n\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class BarChartService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    getData(endpoint: string) {\n        return this._http.get(endpoint)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/barchart/view.html",
    "content": "<div class=\"ui  center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleChartProperties()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig && barChartType == 'normalizedVertical'\" style=\"min-height: 300px\">\n                <ngx-charts-bar-vertical-normalized\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [gradient]=\"gradient\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [barPadding]=15\n                        (select)=\"drillDown($event)\">\n                </ngx-charts-bar-vertical-normalized>\n            </div>\n            <div *ngIf=\"!inConfig && barChartType == 'normalizedHorizontal'\" style=\"min-height: 300px\">\n                <ngx-charts-bar-horizontal-normalized\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [gradient]=\"gradient\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [barPadding]=15\n                        (select)=\"drillDown($event)\">\n                </ngx-charts-bar-horizontal-normalized>\n            </div>\n            <div *ngIf=\"!inConfig && barChartType == 'stackedHorizontal'\" style=\"min-height: 300px\">\n                <ngx-charts-bar-horizontal-stacked\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [gradient]=\"gradient\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [showDataLabel]=\"showDataLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [barPadding]=15\n                        (select)=\"drillDown($event)\">\n                </ngx-charts-bar-horizontal-stacked>\n            </div>\n            <div *ngIf=\"!inConfig && barChartType == 'stackedVertical'\" style=\"min-height: 300px\">\n                <ngx-charts-bar-vertical-stacked\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [gradient]=\"gradient\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [showDataLabel]=\"showDataLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [barPadding]=15\n                        (select)=\"drillDown($event)\">\n                </ngx-charts-bar-vertical-stacked>\n            </div>\n        </div>\n    </div>\n\n    <!-- use the side bar content -->\n    <div *ngIf=\"globalOptions.displayGadgetOptionsInSideBar == true\" class=\"ui sidebar left vertical menu\"\n         #chartOptionsSideBar_tag>\n        <br>\n        <div class=\"ct-title\">{{title}}</div>\n        <br>\n        <app-dynamic-form\n                [gadgetTags]=\"gadgetTags\"\n                [propertyPages]=\"propertyPages\"\n                [instanceId]=\"instanceId\"\n                (updatePropertiesEvent)=\"updateProperties($event)\">\n        </app-dynamic-form>\n    </div>\n\n\n    <app-dynamic-form *ngIf=\"inConfig && globalOptions.displayGadgetOptionsInSideBar == false\"\n                      [gadgetTags]=\"gadgetTags\"\n                      [propertyPages]=\"propertyPages\"\n                      [instanceId]=\"instanceId\"\n                      (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/gadgets/bubble/bubble-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {BubbleService} from './service';\nimport {Router} from '@angular/router';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class BubbleGadgetComponent extends GadgetBase {\n\n    // chart options\n    showXAxis = true;\n    showYAxis = true;\n    gradient = true;\n    showLegend = true;\n    showXAxisLabel = true;\n    showYAxisLabel = true;\n    yAxisLabel = 'Available';\n    xAxisLabel = 'Total';\n    view: any[];\n    data: any[] = [];\n    colorScheme: any = {\n        domain: ['#00ff00', '#4800ff', '#4894FF', '#AF0854']\n    };\n\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _bubbleService: BubbleService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService,\n                private _route: Router) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun(): void {\n\n        // this.run();\n    }\n\n    public run() {\n\n        this.data = [];\n        this.initializeRunState(true);\n        this.updateData(null);\n\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(_data: any[]) {\n\n        this._bubbleService.getMockData().subscribe(data => {\n\n                Object.assign(this, {data});\n\n                console.log(data);\n\n            },\n            error => this.handleError(error));\n    }\n\n    public drillDown(data) {\n        this._route.navigate(['/detail'], {});\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        /*\n        this.title = updatedPropsObject.title;\n        this.showXAxis = updatedPropsObject.chart_properties;\n        this.showYAxis = updatedPropsObject.chart_properties;\n        this.gradient = updatedPropsObject.chart_properties;\n        this.showLegend = updatedPropsObject.chart_properties;\n        this.showXAxisLabel = updatedPropsObject.chart_properties;\n        this.showYAxisLabel = updatedPropsObject.chart_properties;\n        */\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/bubble/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\n\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class BubbleService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    getMockData() {\n        return this._http.get('/assets/api/chart-mock-bubble-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/bubble/view.html",
    "content": "<div  class=\"ui  center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig\" style=\"min-height: 275px\">\n                <ngx-charts-bubble-chart\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\">\n                </ngx-charts-bubble-chart>\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/gadgets/cpu/cpu-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {CPUService} from './service';\nimport {Router} from '@angular/router';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class CPUGadgetComponent extends GadgetBase {\n\n    // chart options\n    showXAxis = true;\n    showYAxis = true;\n    gradient = true;\n    showLegend = true;\n    showXAxisLabel = true;\n    showYAxisLabel = true;\n    yAxisLabel = 'Available CPUs';\n    xAxisLabel = 'Percent Utilization';\n    view: any[];\n    cpu: any[] = [];\n    colorScheme: any = {\n        domain: ['#0d5481', '#0AFF16']\n    };\n\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _cpuService: CPUService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService,\n                private _route: Router) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun(): void {\n\n        this.run();\n    }\n\n    public run() {\n\n        this.cpu = [];\n        this.initializeRunState(true);\n        this.updateData(null);\n\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n        this._cpuService.getMockData().subscribe(cpu => {\n\n                Object.assign(this, {cpu});\n\n            },\n            error => this.handleError(error));\n    }\n\n    public drillDown(data) {\n        this._route.navigate(['/detail'], {\n\n        });\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.showXAxis = updatedPropsObject.chart_properties;\n        this.showYAxis = updatedPropsObject.chart_properties;\n        this.gradient = updatedPropsObject.chart_properties;\n        this.showLegend = updatedPropsObject.chart_properties;\n        this.showXAxisLabel = updatedPropsObject.chart_properties;\n        this.showYAxisLabel = updatedPropsObject.chart_properties;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/cpu/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\n\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class CPUService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    getMockData() {\n        return this._http.get('/assets/api/cpu-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/cpu/view.html",
    "content": "<div  class=\"ui  center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig\" style=\"min-height: 275px\">\n                <ngx-charts-bar-horizontal-normalized\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"cpu\"\n                        [gradient]=\"gradient\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [barPadding]=30\n                        (select)=\"drillDown($event)\">\n                </ngx-charts-bar-horizontal-normalized>\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/gadgets/cpum/cpu.model.ts",
    "content": "\nimport {Series} from '../_common/base-chart-models/series.model';\nimport {Bar} from '../_common/base-chart-models/bar.model';\n\nexport class CPUChartMetric extends Bar {\n\n    data: any;\n\n    constructor(data: any, name: string, series: Array<Series>) {\n        super(name, series);\n        this.data = data;\n\n    }\n}\n\n"
  },
  {
    "path": "src/app/gadgets/cpum/cpum-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {timer} from 'rxjs';\nimport {ObservableWebSocketService} from '../../services/websocket-service';\nimport {ErrorHandler} from '../../error/error-handler';\nimport {CPUChartMetric} from './cpu.model';\nimport {Series} from '../_common/base-chart-models/series.model';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class CPUMGadgetComponent extends GadgetBase implements OnDestroy, OnInit {\n\n    // chart options\n    gradient = true;\n    legend = false;\n    xAxis = true;\n    yAxis = true;\n    showGridLines = true;\n    showXAxisLabel = true;\n    showYAxisLabel = false;\n    xAxisLabel = 'Available CPUs';\n    yAxisLabel = 'Percent Utilization';\n    view: any[];\n    chartData: any[] = [];\n    colorScheme: any = {\n        domain: ['#0AFF16', '#0d5481']\n    };\n    webSocket: any;\n    waitForConnectionDelay = 2000;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                private _webSocketService: ObservableWebSocketService,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService,\n        );\n    }\n\n    public preRun(): void {\n    }\n\n    public run() {\n\n        this.initializeRunState(false);\n\n        this.webSocket = this._webSocketService.createObservableWebSocket(this.getEndPoint().address).subscribe(data => {\n\n                const dataObject = JSON.parse(data);\n\n                this.updateGraph(dataObject);\n\n            },\n            error => {\n                /**\n                 * todo improve this error handling\n                 * @type {{status: string; statusText: string; resource: string}}\n                 */\n                const errMsg = {\n                    status: error.code + '',\n                    statusText: ErrorHandler.getWebSocketErrorReason(error),\n                    resource: this.getEndPoint().address\n                };\n                this.handleError(ErrorHandler.getErrorObject(errMsg));\n            },\n            () => {\n\n                if (this.inRun) {\n\n                    /**\n                     * todo improve this error handling\n                     * @type {{status: string; statusText: string; resource: string}}\n                     */\n                    const errMsg = {\n                        status: 'disconnected',\n                        statusText: 'Service was interrupted while the gadget was running!',\n                        resource: this.getEndPoint().address\n                    };\n                    this.handleError(ErrorHandler.getErrorObject(errMsg));\n                }\n            }\n        );\n\n        /**\n         * todo remove dependency on timer\n         * @type {Observable<number>}\n         */\n        const _timer = timer(this.waitForConnectionDelay);\n\n        _timer.subscribe(t => {\n\n            // todo test whether we are connected of not\n            this._webSocketService.sendMessage('start');\n\n            this.setInRunState();\n\n\n        });\n    }\n\n    public stop() {\n        this.setStopState(true);\n\n        try {\n\n            this._webSocketService.sendMessage('stop');\n\n            this.webSocket.unsubscribe();\n\n            this.updateGraph(null);\n\n        } catch (error) {\n            this.handleError(error);\n        }\n\n        this.actionInitiated = false;\n\n    }\n\n    public updateGraph(cpus: Array<any>) {\n\n        /** todo\n         * i18n\n         */\n        const chartData: any = [];\n        let id = 0;\n\n        if (cpus) {\n            cpus.forEach(cpuData => {\n\n                const value = cpuData['utilPct'];\n\n                const series: Array<Series> = [];\n\n                series.push(new Series('used', value));\n                series.push(new Series('available', 100 - value));\n\n                /** todo\n                 * determine how to get access to the data from the chart for drill down purposes\n                 * @type {CPUChartMetric}\n                 */\n                const cpuChartMetric = new CPUChartMetric(cpuData, 'CPU ' + id++, series);\n\n                chartData.push(cpuChartMetric);\n\n            });\n        }\n\n        Object.assign(this, {chartData});\n\n    }\n\n\n    public updateData(data: any[]) {\n\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n\n        this.title = updatedPropsObject.title;\n        this.gradient = updatedPropsObject.gradient;\n        this.legend = updatedPropsObject.legend;\n        this.xAxis = updatedPropsObject.xAxis;\n        this.yAxis = updatedPropsObject.yAxis;\n        this.showGridLines = updatedPropsObject.showGridLines;\n        this.showXAxisLabel = updatedPropsObject.showXAxisLabel;\n        this.showYAxisLabel = updatedPropsObject.showYAxisLabel;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n    }\n\n    public ngOnDestroy() {\n\n        this.stop();\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/cpum/view.html",
    "content": "<div class=\"ui  center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"heart icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig\" style=\"min-height: 275px\">\n                <ngx-charts-bar-vertical-normalized\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"chartData\"\n                        [gradient]=\"gradient\"\n                        [legend]=\"legend\"\n                        [xAxis]=\"xAxis\"\n                        [yAxis]=\"yAxis\"\n                        [showGridLines]=\"showGridLines\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [barPadding]=30\n                        (select)=\"drillDownPopUp.showDetail($event)\">\n                </ngx-charts-bar-vertical-normalized>\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n    <div class=\"ui bottom attached\" *ngIf=\"actionInitiated\">\n        <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n    </div>\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/gadgets/disk/disk-gadget.component.ts",
    "content": "import {\n    ChangeDetectorRef, Component\n} from '@angular/core';\n\nimport {\n    style, trigger, animate, transition, state\n} from '@angular/animations';\n\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {DiskService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css'],\n    animations: [\n\n        trigger('accordion', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('700ms ease-in-out')),\n            transition('out => in', animate('300ms ease-in-out'))\n        ]),\n        trigger('accordion2', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('300ms ease-in-out')),\n            transition('out => in', animate('800ms ease-in-out'))\n        ])\n    ]\n})\nexport class DiskGadgetComponent extends GadgetBase {\n\n    topic: any;\n\n    showOperationControls = false;\n\n    data: any;\n\n    threshold: string;\n\n    badColorScheme = {\n        domain: ['#a10910', '#DDDDDD']\n    };\n    goodColorScheme = {\n        domain: ['#00c700', '#DDDDDD']\n    };\n    used;\n    avail;\n\n    detailMenuOpen: string;\n\n    colorScheme = this.goodColorScheme;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _diskService: DiskService,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n        this.run();\n        this.setTopic();\n    }\n\n\n    public preRun(): void {\n\n        this.threshold = this.getPropFromPropertyPages('threshold');\n        this.detailMenuOpen = 'out';\n\n    }\n\n\n    public run() {\n        this.data = [];\n        this.initializeRunState(true);\n        this.updateData(null);\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n        this._diskService.getMockData().subscribe(_data => {\n                this.data = _data;\n\n                const thresholdVal = Number(this.threshold);\n\n                if (this.data[0].value < thresholdVal) {\n                    this.colorScheme = this.goodColorScheme;\n                } else {\n                    this.colorScheme = this.badColorScheme;\n                }\n\n                this.used = this.data[0].value;\n                this.avail = this.data[1].value;\n\n            },\n            error => this.handleError(error));\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.threshold = updatedPropsObject.threshold;\n        this.title = updatedPropsObject.title;\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.run();\n\n\n    }\n    setTopic() {\n        this._diskService.getHelpTopic().subscribe(data => {\n\n            this.topic = data;\n\n        });\n    }\n    toggleAcordion(): void {\n\n        this.detailMenuOpen = this.detailMenuOpen === 'out' ? 'in' : 'out';\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/disk/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\n\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {TrendLineService} from '../trend-line/service';\nimport {timer, Observable} from 'rxjs';\nimport {catchError} from \"rxjs/operators\";\nimport {HttpClient} from '@angular/common/http';\n\n@Injectable()\nexport class DiskService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get() {\n        return this._http.get('/assets/api/disk-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n    getHelpTopic() {\n\n        return this._http.get('/assets/api/disk-help-model.json') .pipe(\n            catchError(RuntimeService.handleError)\n        );\n    }\n\n    getMockData() {\n        return new Observable(observer => {\n            timer(500, 5000).subscribe(t => {\n\n                const used = TrendLineService.getRandomArbitrary(0, 100);\n                const available = 100 - used;\n\n                const data = [\n                    {\n                        'name': 'used',\n                        'value': used\n                    },\n                    {\n                        'name': 'available',\n                        'value': available\n                    }\n                ];\n                observer.next(data);\n            });\n        });\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/disk/view.html",
    "content": "<div class=\"ui center aligned  segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"heart icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\"\n            (helpEvent)=\"helpModal.showHelp()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <!--<div>{{avail}} {{used}}</div> -->\n            <div *ngIf=\"!inConfig\" style=\"max-height: 300px; max-width: 400px; min-height: 250px\">\n\n                <ngx-charts-pie-chart *ngIf=\"!inConfig\"\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [legend]=\"true\"\n                        [explodeSlices]=\"false\"\n                        [labels]=\"false\"\n                        [doughnut]=\"true\"\n                        [gradient]=\"false\"\n                        [arcWidth]=\".4\"\n                        (select)=\"drillDownPopUp.showDetail($event)\">\n                </ngx-charts-pie-chart>\n\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n    <app-help-modal #helpModal [topic]=\"topic\"></app-help-modal>\n\n    <br>\n    <div style=\"display: block !important;\"  [@accordion]=\"detailMenuOpen\">\n\n        <table class=\"ui two column table\" [@accordion2]=\"detailMenuOpen\">\n            <thead>\n            <tr>\n                <th>Device ID</th>\n                <th>Type</th>\n            </tr>\n            </thead>\n            <tbody>\n            <tr>\n                <td>safiow4lkf8adfkadfadf</td>\n                <td>ISCSI</td>\n            </tr>\n            </tbody>\n        </table>\n        <table class=\"ui two column table\" [@accordion2]=\"detailMenuOpen\">\n            <thead>\n            <tr>\n                <th>Allocated</th>\n                <th>Available</th>\n\n            </tr>\n            </thead>\n            <tbody>\n            <tr>\n                <td>123123 TB</td>\n                <td>323232342 TB</td>\n\n            </tr>\n            </tbody>\n        </table>\n        <table class=\"ui three column table\" [@accordion2]=\"detailMenuOpen\">\n            <thead>\n            <tr>\n                <th>Read</th>\n                <th>Write</th>\n                <th>Latency</th>\n            </tr>\n            </thead>\n            <tbody>\n            <tr>\n                <td>100 ms</td>\n                <td>10 ms</td>\n                <td>10 ms</td>\n            </tr>\n            </tbody>\n        </table>\n        <br>\n    </div>\n\n\n\n    <div *ngIf=\"!inConfig\" class=\"ui bottom right attached label\" style=\"background-color: white\"><i\n            class=\"large chevron icon\" (click)=\"toggleAcordion()\" [ngClass]=\"{'up':detailMenuOpen == 'in', 'down': detailMenuOpen=='out'}\"\n            style=\"color:lightgrey\"></i></div>\n\n\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/donut/donut-gadget.component.ts",
    "content": "import {\n    ChangeDetectorRef, Component, OnDestroy\n} from '@angular/core';\n\nimport {\n    style, trigger, animate, transition, state\n} from '@angular/animations';\n\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {DonutService} from './service';\nimport {APITokenService} from '../../api-token/api-token.service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css'],\n    animations: [\n\n        trigger('accordion', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('700ms ease-in-out')),\n            transition('out => in', animate('300ms ease-in-out'))\n        ]),\n        trigger('accordion2', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('300ms ease-in-out')),\n            transition('out => in', animate('800ms ease-in-out'))\n        ])\n    ]\n})\nexport class DonutGadgetComponent extends GadgetBase implements OnDestroy {\n\n    topic: any;\n    data = {};\n    colorScheme = {\n        domain: ['#0cd057', '#3f8eff', '#9a0101']\n    };\n    detailMenuOpen: string;\n    donutServiceSubscription: any;\n\n    // gadget properties\n    autoCompliance: boolean;\n    complianceFrequency: number;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _donutService: DonutService,\n                protected  _apiTokenService: APITokenService,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n    }\n\n    public preRun(): void {\n\n        this.setTopic();\n        this.setProperties();\n        this.run();\n\n    }\n\n    public run() {\n\n        this.initializeRunState(true);\n        this.updateData(null);\n    }\n\n    public stop() {\n\n        if (this.donutServiceSubscription) {\n            this.donutServiceSubscription.unsubscribe();\n        }\n        this.setStopState(false);\n    }\n\n\n    public updateData(data: any[]) {\n\n        this.donutServiceSubscription = this._donutService.poll().subscribe(donutData => {\n\n            const me = this;\n\n            this._donutService.get().subscribe(_data => {\n\n                    me.data = _data;\n                },\n                error => this.handleError(error));\n        });\n    }\n\n\n    public updateProperties(updatedProperties: any) {\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.autoCompliance = updatedPropsObject.auto;\n        this.complianceFrequency = updatedPropsObject.frequency;\n        this.showOperationControls = true;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n    }\n\n    setTopic() {\n        this._donutService.getHelpTopic().subscribe(data => {\n            this.topic = data;\n        });\n    }\n\n    public setProperties() {\n\n        this.title = this.getPropFromPropertyPages('title');\n        this.detailMenuOpen = 'out';\n    }\n\n\n    toggleAccordion(): void {\n\n        this.detailMenuOpen = this.detailMenuOpen === 'out' ? 'in' : 'out';\n\n    }\n\n    public ngOnDestroy() {\n\n        this.stop();\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/donut/drill-down-component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    ViewChild, ElementRef, AfterViewInit, Component\n} from '@angular/core';\n\nimport {\n    style, state, trigger, animate, transition\n} from '@angular/animations';\n\nimport {Facet, Tag} from '../../facet/facet-model';\nimport {DonutService} from './service';\n\n\ndeclare var jQuery: any;\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-drill-down-modal',\n    moduleId: module.id,\n    templateUrl: './drill-down.html',\n    styleUrls: ['drill-down-style.css'],\n    animations: [\n\n        trigger('contentSwitch', [\n            state('inactive', style({\n                opacity: 0\n            })),\n            state('active', style({\n                opacity: 1\n            })),\n            transition('inactive => active', animate('750ms ease-in')),\n            transition('active => inactive', animate('750ms ease-out'))\n        ]),\n        trigger('tabSwitch', [\n            state('inactive', style({\n                opacity: .75\n            })),\n            state('active', style({\n                opacity: 1\n            })),\n            transition('inactive => active', animate('750ms ease-in')),\n            transition('active => inactive', animate('750ms ease-out'))\n        ])\n    ]\n})\nexport class DrillDownComponent implements AfterViewInit {\n\n    modalicon: string;\n    modalheader: string;\n    modalconfig: string;\n\n    chartSelectedName: string;\n    chartSelectedValue: number;\n\n    objects: any[];\n    objecNameList: string[];\n\n    placeHolderText = 'Begin typing a name';\n\n    layoutColumnOneWidth = 'six';\n    layoutColumnTwoWidth = 'ten';\n    facetTags: Array<Facet> = [];\n    listHeader = 'Header Name';\n\n    dropZone1Count = 0;\n    dropZone2Count = 0;\n    dropZone3Count = 0;\n\n    hideRightColumn = false;\n    leftColumnWidth = 'eleven';\n\n\n\n    @ViewChild('drillmodal_tag') modalaRef: ElementRef;\n    configModal: any;\n\n    constructor(private _donutService: DonutService) {\n\n    }\n\n    showMessageModal(icon: string, header: string, message: string) {\n        this.modalicon = icon;\n        this.modalheader = header;\n        this.modalconfig = message;\n        this.configModal.modal('show');\n\n    }\n\n\n    hideMessageModal() {\n        this.modalicon = '';\n        this.modalheader = '';\n        this.modalconfig = '';\n        this.configModal.modal('hide');\n    }\n\n\n    ngAfterViewInit() {\n        this.configModal = jQuery(this.modalaRef.nativeElement);\n        this.configModal.modal('hide');\n    }\n\n    showDrillDownDetail($event) {\n\n        if (typeof $event === 'string') {\n\n            this.chartSelectedName = $event.toLocaleLowerCase();\n\n        } else {\n\n            this.chartSelectedName = $event['name'].toString().toLocaleLowerCase();\n            this.chartSelectedValue = $event['value'];\n        }\n\n        if (this.chartSelectedName === 'non-compliant') {\n\n            this.hideRightColumn = false;\n            this.leftColumnWidth = 'eleven';\n\n        } else {\n\n            this.hideRightColumn = true;\n            this.leftColumnWidth = 'sixteen';\n        }\n\n        this._donutService.get().subscribe(_data => {\n\n            _data.forEach(object => {\n\n                if (object['name'] === this.chartSelectedName) {\n\n                    this.processObjects(object['detail']);\n                    this.setFacets();\n                    this.showMessageModal(null, 'Detail', null);\n\n                }\n            });\n        });\n    }\n\n    showDetail($event) {\n\n        const data: string = JSON.stringify($event, null, 4);\n        this.showMessageModal(null, 'Detail', data);\n\n\n    }\n\n    processObjects(objectsToProcess: any) {\n\n\n        this.objects = [];\n        this.objecNameList = [];\n\n        Object.assign(this.objects, objectsToProcess);\n\n        this.objects.forEach(name => {\n\n            this.objecNameList.push(name['name']);\n\n        });\n\n    }\n\n    updateDropZone1(object: any) {\n        if (object.dragData === 'all') {\n            this.dropZone1Count += this.objects.length;\n        } else {\n            this.dropZone1Count++;\n        }\n    }\n\n    updateDropZone2(object: any) {\n        if (object.dragData === 'all') {\n            this.dropZone2Count += this.objects.length;\n        } else {\n            this.dropZone2Count++;\n        }\n    }\n\n    updateDropZone3(object: any) {\n        if (object.dragData === 'all') {\n            this.dropZone3Count += this.objects.length;\n        } else {\n            this.dropZone3Count++;\n        }\n    }\n\n    setFacets() {\n\n        this.facetTags.length = 0;\n\n        const t1 = new Tag('Tag1');\n        const t2 = new Tag('Tag2');\n        const a1 = new Array<Tag>();\n        a1.push(t1);\n        a1.push(t2);\n        const f1 = new Facet('Category A', a1);\n\n        const t3 = new Tag('Tag3');\n        const t4 = new Tag('Tag4');\n\n        const a2 = new Array<Tag>();\n        a2.push(t3);\n        a2.push(t4);\n        const f2 = new Facet('Category B', a2);\n\n        this.facetTags.push(f1);\n        this.facetTags.push(f2);\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/donut/drill-down-style.css",
    "content": "h3 {\n    font-weight: 400;\n}\n\n.drill-down-blue {\n\n    color: #2c83d0\n\n}"
  },
  {
    "path": "src/app/gadgets/donut/drill-down.html",
    "content": "<div class=\"ui long modal\" #drillmodal_tag>\n    <div class=\"header\">\n        <h2>{{modalheader}}</h2>\n    </div>\n\n\n    <div class=\"content\">\n\n        {{modalconfig}}\n\n\n        <div class=\"ui grid\">\n\n            <div class=\"{{leftColumnWidth}} wide column\" >\n\n            <h3>There are <span class=\"drill-down-blue\">{{chartSelectedValue}} </span> item(s) <span\n                    class=\"drill-down-blue\">{{chartSelectedName}}</span></h3>\n            <app-data-list\n\n                    [objectList]=\"objects\"\n                    [objectTitleList]=\"objecNameList\"\n                    [placeHolderText]=\"placeHolderText\"\n                    [layoutColumnOneWidth]=\"layoutColumnOneWidth\"\n                    [layoutColumnTwoWidth]=\"layoutColumnTwoWidth\"\n                    [listHeader]=\"listHeader\"\n                    [facetTags]=\"facetTags\">\n\n                <ng-template let-item=\"$implicit\">\n\n\n                    <mat-expansion-panel dnd-draggable [dragEnabled]=\"true\" dragData={{item.name}}>\n                        <mat-expansion-panel-header>\n                            <mat-panel-title>\n                                {{item.name}}\n                            </mat-panel-title>\n                            <mat-panel-description>\n                            </mat-panel-description>\n                        </mat-expansion-panel-header>\n\n                        <p>Expansion data </p>\n\n                    </mat-expansion-panel>\n\n                </ng-template>\n\n            </app-data-list>\n\n\n        </div>\n        <div class=\"five wide column\" *ngIf=\"hideRightColumn == false\">\n\n            <h3>Compliance Policies</h3>\n\n            <div style=\"max-height: 600px; overflow-y: auto; overflow-x: hidden\">\n\n                <div dnd-droppable\n                     (onDropSuccess)=\"updateDropZone1($event)\">\n                    <table class=\"ui small celled striped table\">\n                        <thead>\n                        <tr>\n                            <th>Policy A</th>\n                        </tr>\n                        </thead>\n                        <tbody>\n                        <tr>\n                            <td style=\"text-align: center\"> ({{dropZone1Count}})</td>\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n                <br>\n                <div dnd-droppable\n                     (onDropSuccess)=\"updateDropZone2($event)\">\n                    <table class=\"ui small celled striped table\">\n                        <thead>\n                        <tr>\n                            <th>Policy B</th>\n                        </tr>\n                        </thead>\n                        <tbody>\n                        <tr>\n                            <td style=\"text-align: center\">({{dropZone2Count}})</td>\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n                <br>\n                <div dnd-droppable\n                     (onDropSuccess)=\"updateDropZone3($event)\">\n                    <table class=\"ui small celled striped table\">\n                        <thead>\n                        <tr>\n                            <th>Policy C</th>\n                        </tr>\n                        </thead>\n                        <tbody>\n                        <tr>\n                            <td style=\"text-align: center\">({{dropZone3Count}})</td>\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n            </div>\n\n        </div>\n\n    </div>\n\n    <br>\n    <div class=\"actions\">\n        <div class=\"ui approve button\">Close</div>\n    </div>\n</div>\n</div>"
  },
  {
    "path": "src/app/gadgets/donut/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\n\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {timer, Observable} from 'rxjs';\nimport {catchError} from \"rxjs/operators\";\nimport {HttpClient} from '@angular/common/http';\n\n@Injectable()\nexport class DonutService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get() {\n        return this._http.get<any[]>('/assets/api/donut-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n    getHelpTopic() {\n\n        return this._http.get('/assets/api/disk-help-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n    poll() {\n        return new Observable(observer => {\n            timer(500, 10000).subscribe(t => {\n                observer.next();\n            });\n        });\n    }\n\n    complianceJob(event: string) {\n\n        /**\n         *         post a request to the backend to start a compliance operation. The get API above will reflect the\n         *         changing results of the compliance job. The compliance job will have an event action that dictates\n         *         state transitions stop, start, pause, abort, status.\n         */\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/donut/view.html",
    "content": "<div class=\"ui center aligned  segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"heart icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\"\n            (helpEvent)=\"helpModal.showHelp()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <!--<div>{{avail}} {{used}}</div> -->\n            <div *ngIf=\"!inConfig\" style=\"min-height: 270px\">\n\n                <ngx-charts-pie-chart *ngIf=\"!inConfig\"\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [legend]=\"true\"\n                        [explodeSlices]=\"false\"\n                        [labels]=\"false\"\n                        [doughnut]=\"true\"\n                        [gradient]=\"false\"\n                        [legendTitle]=\"legendTitle\"\n                        [arcWidth]=\".5\"\n                        (select)=\"drillDownPopUp.showDrillDownDetail($event)\">\n                </ngx-charts-pie-chart>\n\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-drill-down-modal #drillDownPopUp></app-drill-down-modal>\n\n    <app-help-modal #helpModal [topic]=\"topic\"></app-help-modal>\n\n    <br>\n    <div style=\"display: block !important;\"  [@accordion]=\"detailMenuOpen\">\n       <h2>Detail Content</h2>\n    </div>\n\n\n    <div *ngIf=\"!inConfig\" class=\"ui bottom right attached label\" style=\"background-color: white\"><i\n            class=\"large chevron icon\" (click)=\"toggleAccordion()\" [ngClass]=\"{'up':detailMenuOpen == 'in', 'down': detailMenuOpen=='out'}\"\n            style=\"color:lightgrey\"></i></div>\n\n\n    <div class=\"ui bottom attached\" *ngIf=\"actionInitiated\" style=\"width:33%\">\n        <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n    </div>\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/edge-service-list/edge-service-list-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, ElementRef, OnDestroy, ViewChild} from '@angular/core';\nimport {\n    style, trigger, animate, transition, state\n} from '@angular/animations';\n\nimport {RuntimeService} from '../../services/runtime.service';\nimport {serviceList} from './service-list';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {EdgeService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\ndeclare var jQuery: any;\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css'],\n    animations: [\n        trigger(\n            'showHideAnimation',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(3000, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(3000, style({opacity: 0}))\n\n                ])\n            ]),\n        trigger('accordion', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('700ms ease-in-out')),\n            transition('out => in', animate('300ms ease-in-out'))\n        ]),\n        trigger('accordion2', [\n            state('in', style({\n                height: '*'\n            })),\n            state('out', style({\n                opacity: '0',\n                height: '0px'\n            })),\n            transition('in => out', animate('300ms ease-in-out')),\n            transition('out => in', animate('800ms ease-in-out'))\n        ])]\n})\nexport class EdgeServiceListGadgetComponent extends GadgetBase implements OnDestroy {\n    // chart options\n    showXAxis = true;\n    showYAxis = true;\n    gradient = true;\n    showLegend = false;\n    showXAxisLabel = true;\n    showYAxisLabel = true;\n    yAxisLabel = 'Tasks';\n    xAxisLabel = 'Proxies';\n    view: any[] = [700, 200];\n    single: any [];\n    colorScheme: any = {\n        domain: ['#0d5481', '#0AFF16', '#da871e', '#D449E1']\n    };\n\n    remoteService: any;\n    detailMenuOpen: string;\n\n    // todo just realy on json\n    edgeServiceList: {\n        active: boolean,\n        host: string,\n        port: number,\n        metaData: any,\n        uri: string,\n        serviceId: string,\n        status: string,\n        runningTaskCount: number\n    }[] = [];\n    selectedUri: string;\n\n    constructor(protected _procMonRuntimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                private _edgeService: EdgeService,\n                protected _optionsService: OptionsService) {\n        super(_procMonRuntimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n        Object.assign(this, {serviceList});\n\n        const single = [];\n\n        Object.assign(this, {single});\n    }\n\n    public preRun(): void {\n        this.detailMenuOpen = 'out';\n    }\n\n    public run() {\n        this.initializeRunState(false);\n\n        const me = this;\n        this.remoteService = this._edgeService.getMicroServices(this.getEndPoint().address).subscribe(results => {\n                const edgeServiceList = [];\n                this.setInRunState();\n\n                if (results instanceof Array) {\n                    results.forEach(function (item) {\n\n                        me._edgeService.getTaskCount(item.uri).subscribe(data => {\n\n                            const i = {\n                                active: false,\n                                host: '',\n                                port: 0,\n                                metaData: {},\n                                uri: '',\n                                serviceId: '',\n                                status: 'UP',\n                                runningTaskCount: 0\n                            };\n                            i['active'] = true;\n                            i['host'] = item.host;\n                            i['port'] = item.port;\n                            i['metaData'] = item.metadata;\n                            i['uri'] = item.uri;\n                            i['serviceId'] = item.serviceId;\n                            i['runningTaskCount'] = data;\n                            edgeServiceList.push(i);\n                            edgeServiceList.sort(function (a, b) {\n                                if (a['port'] < b['port']) {\n                                    return -1;\n                                } else if (a['port'] > b['port']) {\n                                    return 1;\n                                } else {\n                                    return 0;\n                                }\n                            });\n\n                            Object.assign(me.edgeServiceList, edgeServiceList);\n\n                            me.updateGraph();\n                        });\n                    });\n                }\n            }\n            ,\n            error =>\n                this.handleError(error)\n            ,\n            () =>\n                console\n                    .debug(\n                        'Connecting to the service'\n                    ));\n    }\n\n    public checkPoxySelection() {\n        this._edgeService.getSelectedProxy().subscribe(result => {\n            this.selectedUri = result['_body'];\n        });\n    }\n\n    public seedProxiesWithWork() {\n\n        this._edgeService.seedProxiesWithWork().subscribe(data => {\n\n            console.log('job running');\n        });\n\n    }\n\n    public runProxyJob(uri: string) {\n\n        this._edgeService.runJob(uri).subscribe(data => {\n\n            console.log('running job on proxy: ' + uri);\n        });\n\n    }\n\n    public stop() {\n        this.setStopState(true);\n\n        if (this.remoteService) {\n            this.remoteService.unsubscribe();\n        }\n        this.edgeServiceList.length = 0;\n        this.actionInitiated = false;\n\n    }\n\n    public updateData(data: any[]) {\n\n        data.forEach(function (item) {\n\n            serviceList.forEach(function (service) {\n\n                if (item.toString().includes(service.pseudoName)) {\n                    service.active = true;\n                    service.processId = item.toString().split(':')[0];\n\n                }\n            });\n        });\n\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n    }\n\n    updateGraph() {\n\n        const single = [];\n        this.edgeServiceList.forEach(item => {\n            single.push({\n                'name': item.port + ' ' + item.host,\n                'value': item.runningTaskCount\n            });\n        });\n\n        single.sort(function (a, b) {\n            if (a['name'] < b['name']) {\n                return -1;\n            } else if (a['name'] > b['name']) {\n                return 1;\n            } else {\n                return 0;\n            }\n        });\n\n        Object.assign(this, {single});\n\n    }\n\n    public ngOnDestroy() {\n\n        this.stop();\n\n    }\n\n    toggleAcordion(): void {\n\n        this.detailMenuOpen = this.detailMenuOpen === 'out' ? 'in' : 'out';\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/edge-service-list/service-list.ts",
    "content": "/**\n * Created by jayhamilton on 1/28/17.\n */\nexport const serviceList: {\n    active: boolean,\n    applicationName: string,\n    description: string,\n    icon: string,\n    pseudoName: string,\n    processId: string}[] = [\n    {\n        active: false,\n        applicationName: 'Virgo',\n        description: 'Main ECX Application container that manages all of the ECX functions.',\n        icon: 'images/donut.png',\n        pseudoName: 'ECX',\n        processId: ''\n    },\n    {\n        active: false,\n        applicationName: 'Eureka',\n        description: 'This is a microservice discovery service. Used for such items as VADP Proxy.',\n        icon: 'images/donut.png',\n        pseudoName: 'Eureka',\n        processId: ''\n    },\n    {\n        active: false,\n        applicationName: 'PostGresql',\n        description: 'This is a database server used for job management and security.',\n        icon: 'images/donut.png',\n        pseudoName: 'SQL DB',\n        processId: ''\n    },\n    {\n        active: false,\n        applicationName: 'Mongo',\n        description: 'This is a database server used for ECX operation management.',\n        icon: 'images/donut.png',\n        pseudoName: 'Catalog DB',\n        processId: ''\n    },\n    {\n        active: false,\n        applicationName: 'Mongo',\n        description: 'This is a database server used for ECX configuration.',\n        icon: 'images/donut.png',\n        pseudoName: 'Configuration DB',\n        processId: ''\n    },\n\n];\n"
  },
  {
    "path": "src/app/gadgets/edge-service-list/service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {timer, Observable} from 'rxjs';\nimport {catchError} from \"rxjs/operators\";\nimport {HttpClient} from '@angular/common/http';\n\n@Injectable()\nexport class EdgeService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    getSelectedProxy() {\n        return this._http.get('http://localhost:9090/select')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n    // http://localhost:9090/service-instances/vadp'\n    getMicroServices(url: string) {\n        return new Observable(observer => {\n            timer(500, 5000).subscribe(t => {\n                this._http.get(url).subscribe(data => {\n\n                    observer.next(data);\n                }),\n                    catchError(RuntimeService.handleError);\n            });\n        });\n    }\n\n    getTaskCount(uri: string) {\n        console.log('Getting task count for: ' + uri);\n        return this._http.get<number>(uri + '/task')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n    seedProxiesWithWork() {\n        return this._http.post('http://localhost:9090/run', null, null)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n    runJob(uri: string) {\n        return this._http.post(uri + '/run', null, null)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n\n    getGraphInfo() {\n        return this._http.get('/assets/api/disk-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n\n\n"
  },
  {
    "path": "src/app/gadgets/edge-service-list/view.html",
    "content": "<div  class=\"ui   segment left aligned gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui divided selection list\" *ngIf=\"!inConfig\">\n\n        <table class=\"ui padded table\">\n            <tr>\n                <td>\n                    <button class=\"ui basic blue button\" (click)=\"checkPoxySelection()\">Test Load Balance Algorithm\n                    </button>\n                </td>\n                <td>\n                    <button class=\"ui basic blue button\" (click)=\"seedProxiesWithWork()\">Add VMs to Proxies\n                    </button>\n                </td>\n                <td>\n                    <select  style=\"text-overflow: ellipsis; text-align:center; color:#2185D0; background: transparent;padding: 10px;font-size: 14px;line-height: 1; border-width:1px;border-style:solid; border-color:#2185D0; height: 37px;-webkit-appearance: none;\n   }\">\n                        <option value=\"none\">Affinity</option>\n                        <option value=\"lan\"> lan</option>\n                        <option value=\"san\"> san</option>\n                    </select>\n                </td>\n                <td>\n                    <select  style=\"text-overflow: ellipsis; text-align:center; color:#2185D0; background: transparent;padding: 10px;font-size: 14px;line-height: 1; border-width:1px;border-style:solid; border-color:#2185D0; height: 37px;-webkit-appearance: none;\n   }\">\n                        <option value=\"none\">Proximity</option>\n                        <option value=\"lan\"> ny</option>\n                        <option value=\"san\"> nj</option>\n                        <option value=\"san\"> cal</option>\n                    </select>\n                </td>\n            </tr>\n        </table>\n\n        <table class=\"ui padded table\">\n            <thead>\n            <th>\n                Status\n            </th>\n            <th>\n                Name\n            </th>\n            <th>\n                Host\n            </th>\n            <th>\n                Port\n            </th>\n            <th>\n                Select\n            </th>\n            <th>\n                Tasks\n            </th>\n\n            <th colspan=\"2\">\n                Meta-Data\n            </th>\n            <th>Run Job On Proxy</th>\n            </thead>\n            <tr *ngFor=\"let serviceItem of edgeServiceList\" class=\"item\">\n                <td>\n                    <div class=\"left floated content\">\n                        <i *ngIf=\"serviceItem.status == 'UP'\" class=\"big green check icon\"></i>\n                        <i *ngIf=\"serviceItem.processId==''\" class=\"big red minus circle\"></i>\n                    </div>\n                </td>\n                <td><a class=\"header\">{{serviceItem.serviceId}}</a></td>\n                <td><a class=\"header\">{{serviceItem.host}}</a></td>\n                <td><a class=\"header\">{{serviceItem.port}}</a></td>\n                <td>\n                    <div class=\"left floated content\">\n                        <i *ngIf=\"serviceItem.uri == selectedUri\" [@showHideAnimation]\n                           class=\"big blue check icon\"></i>\n                    </div>\n                </td>\n                <td>{{serviceItem.runningTaskCount}}</td>\n                <td>{{serviceItem.metaData.affinity}}</td>\n                <td>{{serviceItem.metaData.proximity}}</td>\n                <td>\n                    <button class=\"ui basic blue button\" (click)=\"runProxyJob(serviceItem.uri)\">Run</button>\n                </td>\n            </tr>\n        </table>\n        <div style=\"display: block !important;\" [@accordion]=\"detailMenuOpen\">\n            <table class=\"ui table\" style=\"border:none !important\" [@accordion2]=\"detailMenuOpen\">\n                <tbody>\n                <tr>\n                    <td>\n                        <ngx-charts-bar-vertical\n                                [view]=\"view\"\n                                [scheme]=\"colorScheme\"\n                                [results]=\"single\"\n                                [gradient]=\"gradient\"\n                                [xAxis]=\"showXAxis\"\n                                [yAxis]=\"showYAxis\"\n                                [legend]=\"showLegend\"\n                                [showXAxisLabel]=\"showXAxisLabel\"\n                                [showYAxisLabel]=\"showYAxisLabel\"\n                                [xAxisLabel]=\"xAxisLabel\"\n                                [yAxisLabel]=\"yAxisLabel\"\n                                [barPadding]=\"20\"\n                                (select)=\"onSelect($event)\">\n                        </ngx-charts-bar-vertical>\n                    </td>\n                </tr>\n                </tbody>\n            </table>\n\n            <br>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                      [gadgetTags]=\"gadgetTags\"\n                      [propertyPages]=\"propertyPages\"\n                      [instanceId]=\"instanceId\"\n                      (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <div *ngIf=\"!inConfig\" class=\"ui bottom right attached label\" style=\"background-color: white\"><i\n            class=\"large chevron icon\" (click)=\"toggleAcordion()\"\n            [ngClass]=\"{'up':detailMenuOpen == 'in', 'down': detailMenuOpen=='out'}\"\n            style=\"color:lightgrey\"></i></div>\n\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/gadget.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {CPUGadgetComponent} from './cpu/cpu-gadget.component';\nimport {CPUMGadgetComponent} from './cpum/cpum-gadget.component';\nimport {DiskGadgetComponent} from './disk/disk-gadget.component';\nimport {MemoryGadgetComponent} from './memory/memory-gadget.component';\nimport {EdgeServiceListGadgetComponent} from './edge-service-list/edge-service-list-gadget.component';\nimport {StatisticGadgetComponent} from './statistic/statistic-gadget.component';\nimport {TrendGadgetComponent} from './trend/trend-gadget.component';\nimport {TrendLineGadgetComponent} from './trend-line/trend-line-gadget.component';\nimport {NewsGadgetComponent} from './news/news-gadget.component';\nimport {TodoGadgetComponent} from './todo/todo-gadget.component';  // todo gadget\nimport {JobAnalysisGadgetComponent} from './job-analysis/job-analysis-gadget.component';\nimport {CPUService} from './cpu/service';\nimport {EdgeService} from './edge-service-list/service';\nimport {StatisticService} from './statistic/service';\nimport {DiskService} from './disk/service';\nimport {TrendService} from './trend/service';\nimport {PropertyListGadgetComponent} from './property-list/property-list-gadget.component';\nimport {DynamicFormModule} from '../dynamic-form/dynamic-form-module';\nimport {ServiceListGadgetComponent} from './service-list/service-list-gadget.component';\nimport {DndModule} from 'ng2-dnd';\nimport {NgxChartsModule} from '@swimlane/ngx-charts';\nimport {GadgetSharedModule} from './_common/gadget-shared.module';\nimport {ErrorHandlerModule} from '../error/error.module';\n\nimport {PortConnectionGadgetComponent} from './port-connection/port-connection-gadget.component';\nimport {\n    MatButtonModule, MatCheckboxModule, MatExpansionModule, MatIconModule, MatInputModule, MatOptionModule,\n    MatProgressBarModule, MatSelectModule\n} from '@angular/material';\nimport {FormsModule} from '@angular/forms';\nimport {StorageObjectListComponent} from './storage-object-list/storage-object-list.component';\nimport {StorageService} from './storage-object-list/service';\nimport {DataListModule} from '../datalist/data-list.module';\nimport {DonutGadgetComponent} from './donut/donut-gadget.component';\nimport {DonutService} from './donut/service';\nimport {APITokenService} from '../api-token/api-token.service';\nimport {DrillDownComponent} from './donut/drill-down-component';\nimport {FacetModule} from '../facet/facet.module';\nimport {TypeAheadInputModule} from '../typeahead-input/typeahead-input.module';\nimport {TodoService} from './todo/service';\nimport {ConnectionService} from './port-connection/service';\nimport {BubbleGadgetComponent} from \"./bubble/bubble-gadget.component\";\nimport {ResultViewComponent} from \"./port-connection/result-view.component\";\nimport {SolutionViewComponent} from \"./port-connection/solution-view.component\";\nimport {BarChartGadgetComponent} from \"./barchart/barchart-gadget.component\";\nimport {BarChartService} from \"./barchart/service\";\nimport {PieChartGadgetComponent} from \"./piechart/piechart-gadget.component\";\nimport {PieChartService} from \"./piechart/service\";  // todo gadget\n\n\n\n\n@NgModule({\n    imports: [\n        CommonModule,\n        GadgetSharedModule,\n        DndModule.forRoot(),\n        DynamicFormModule,\n        ErrorHandlerModule,\n        NgxChartsModule,\n        MatButtonModule,\n        MatIconModule,\n        MatCheckboxModule,\n        MatInputModule,\n        MatProgressBarModule,\n        MatExpansionModule,\n        MatOptionModule,\n        MatSelectModule,\n        FormsModule,\n        FacetModule,\n        TypeAheadInputModule,\n        DataListModule\n    ],\n    declarations: [\n        TodoGadgetComponent,  // todo gadget\n        CPUGadgetComponent,\n        CPUMGadgetComponent,\n        DiskGadgetComponent,\n        MemoryGadgetComponent,\n        EdgeServiceListGadgetComponent,\n        StatisticGadgetComponent,\n        TrendGadgetComponent,\n        TrendLineGadgetComponent,\n        NewsGadgetComponent,\n        JobAnalysisGadgetComponent,\n        StatisticGadgetComponent,\n        PropertyListGadgetComponent,\n        ServiceListGadgetComponent,\n        PortConnectionGadgetComponent,\n        StorageObjectListComponent,\n        DonutGadgetComponent,\n        DrillDownComponent,\n        BubbleGadgetComponent,\n        ResultViewComponent,\n        SolutionViewComponent,\n        BarChartGadgetComponent,\n        PieChartGadgetComponent\n\n    ],\n\n    providers: [TrendService,\n        DiskService,\n        StatisticService,\n        EdgeService,\n        CPUService,\n        StorageService,\n        DonutService,\n        APITokenService,\n        ConnectionService,\n        TodoService,  // todo gadget\n        BarChartService,\n        PieChartService\n    ],\n\n    exports: [\n        TodoGadgetComponent,  // todo gadget\n        CPUGadgetComponent,\n        CPUMGadgetComponent,\n        DiskGadgetComponent,\n        MemoryGadgetComponent,\n        EdgeServiceListGadgetComponent,\n        StatisticGadgetComponent,\n        TrendGadgetComponent,\n        TrendLineGadgetComponent,\n        NewsGadgetComponent,\n        JobAnalysisGadgetComponent,\n        StatisticGadgetComponent,\n        PropertyListGadgetComponent,\n        ServiceListGadgetComponent,\n        PortConnectionGadgetComponent,\n        StorageObjectListComponent,\n        DonutGadgetComponent,\n        BubbleGadgetComponent,\n        BarChartGadgetComponent,\n        PieChartGadgetComponent\n    ]\n})\nexport class GadgetModule {\n}\n\n"
  },
  {
    "path": "src/app/gadgets/job-analysis/ja.css",
    "content": ".example-card {\n    width: 400px;\n}\n\n.example-header-image {\n    background-size: cover;\n}"
  },
  {
    "path": "src/app/gadgets/job-analysis/job-analysis-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {JobAnalysisService} from './service';\nimport {DomSanitizer} from '@angular/platform-browser';\nimport {MatIconRegistry} from '@angular/material';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\ndeclare var d3: any;\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./ja.css']\n})\n\nexport class JobAnalysisGadgetComponent extends GadgetBase {\n\n\n    showOperationControls = false;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _jobAnalysisService: JobAnalysisService,\n                iconRegistry: MatIconRegistry, sanitizer: DomSanitizer,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n        iconRegistry.addSvgIcon(\n            'thumbs-up',\n            sanitizer.bypassSecurityTrustResourceUrl('assets/images/svg-icons/ic_add_white_36px.svg'));\n\n        this.run();\n    }\n\n\n    public preRun(): void {\n    }\n\n    public run() {\n        this.initializeRunState(true);\n\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n    }\n\n\n}\n"
  },
  {
    "path": "src/app/gadgets/job-analysis/model.json",
    "content": "[\n  {\n    \"name\": \"IBM\",\n    \"series\": [\n      {\n        \"name\": \"January\",\n        \"value\": 3453\n      },\n      {\n        \"name\": \"February\",\n        \"value\": 3434434\n      },\n      {\n        \"name\": \"March\",\n        \"value\": 333335\n      },\n      {\n        \"name\": \"April\",\n        \"value\": 434\n      }\n    ]\n  },\n\n  {\n    \"name\": \"NetApp\",\n    \"series\": [\n      {\n        \"name\": \"January\",\n        \"value\": 78\n      },\n      {\n        \"name\": \"February\",\n        \"value\": 82700\n      },\n      {\n        \"name\": \"March\",\n        \"value\": 4333335\n      },\n      {\n        \"name\": \"April\",\n        \"value\": 8345\n      }\n    ]\n  },\n\n  {\n    \"name\": \"Pure\",\n    \"series\": [\n      {\n        \"name\": \"January\",\n        \"value\": 5043344\n      },\n      {\n        \"name\": \"February\",\n        \"value\": 5800\n      },{\n        \"name\": \"March\",\n        \"value\": 333335\n      },\n      {\n        \"name\": \"April\",\n        \"value\": 4343333\n      }\n    ]\n  }\n]"
  },
  {
    "path": "src/app/gadgets/job-analysis/service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n@Injectable()\nexport class JobAnalysisService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get() {\n        return this._http.get('../../plugins/procmon/components/gadgets/trend/model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/job-analysis/view.html",
    "content": "<div class=\"ui center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div *ngIf=\"!inConfig\">\n\n\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                      [gadgetTags]=\"gadgetTags\"\n                      [propertyPages]=\"propertyPages\"\n                      [instanceId]=\"instanceId\"\n                      (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/gadgets/memory/memory-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, OnDestroy} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {timer} from 'rxjs';\nimport {ObservableWebSocketService} from '../../services/websocket-service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class MemoryGadgetComponent extends GadgetBase implements OnDestroy {\n\n    // chart options\n    view: any[];\n    colorScheme = {\n        domain: ['#A13F51', '#5AA454', '#C7B42C']\n    };\n\n    currentValue = '0';\n    previousValue = '0';\n    webSocket: any;\n    waitForConnectionDelay = 2000;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                private _webSocketService: ObservableWebSocketService,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun(): void {\n    }\n\n    public run() {\n\n        this.initializeRunState(false);\n\n        this.webSocket = this._webSocketService.createObservableWebSocket(this.getEndPoint().address).subscribe(data => {\n\n                const dataObject = JSON.parse(data);\n\n                try {\n\n                    let percent = dataObject.used / dataObject.total * 100;\n                    percent = Math.round(percent);\n                    this.updateGraph(percent);\n\n                } catch (error) {\n                    this.handleError(error);\n                }\n\n            },\n            error => {\n\n                console.log(error);\n\n                this.handleError(error);\n            });\n\n\n        const _timer = timer(this.waitForConnectionDelay);\n\n        _timer.subscribe(t => {\n\n            // todo test whether we are connected of not\n            this._webSocketService.sendMessage('start');\n            this.setInRunState();\n\n        });\n    }\n\n    public stop() {\n        this.setStopState(true);\n\n        try {\n\n            this._webSocketService.sendMessage('stop');\n            this.webSocket.unsubscribe();\n\n        } catch (error) {\n\n            this.handleError(error);\n        }\n\n\n        this.actionInitiated = false;\n    }\n\n    public updateData(data: any[]) {\n\n\n    }\n\n    public updateGraph(value: number) {\n\n        if (Number(this.currentValue) > Number(this.previousValue)) {\n            this.previousValue = this.currentValue;\n        }\n\n        this.currentValue = value + '';\n        this.showOperationControls = true;\n\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n    }\n\n    public ngOnDestroy() {\n\n        this.stop();\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/memory/view.html",
    "content": "<div  class=\"ui center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig\" style=\"min-height: 275px\">\n                <ngx-charts-linear-gauge\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [value]=currentValue\n                        [previousValue]=previousValue\n                        [min]=\"0\"\n                        [max]=\"100\"\n                        [units]=\"'percent used'\"\n                        (select)=\"drillDownPopUp.showDetail($event)\">\n                </ngx-charts-linear-gauge>\n\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n</div>\n"
  },
  {
    "path": "src/app/gadgets/news/news-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {NewsService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\nexport class NewsGadgetComponent extends GadgetBase {\n\n    // runtime document subscription\n    news: any;\n    resource: string;\n\n    gadgetHasOperationControls = false;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _newsService: NewsService,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun(): void {\n        this.updateData(null);\n        this.run();\n    }\n\n    public run() {\n        this.news = [];\n        this.initializeRunState(true);\n        this.updateData(null);\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n        this._newsService.get().subscribe(news => {\n                this.news = news;\n            },\n            error => this.handleError(error));\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.setEndPoint(updatedPropsObject.endpoint);\n        this.updateData(null);\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/news/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n@Injectable()\nexport class NewsService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get() {\n        return this._http.get('/assets/api/news-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/news/view.html",
    "content": "<div  class=\"ui center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\" style=\"background-color: #f7f7f7\">\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div *ngIf=\"!inConfig\" style=\"overflow-y:auto; padding-right:5px; padding-left:5px;max-height:800px; min-height: 275px; text-align: left !important; background-color:#f7f7f7\" >\n        <div *ngFor=\"let release of news\" >\n            <h3>{{release.heading}}</h3>\n            <div *ngFor=\"let detail of release.details\" class=\"ui segment\">\n                <h4 style=\"font-weight:500 !important\">{{detail.category}}</h4>\n\n                <div class=\"ui divided items\">\n                    <div class=\"item\" *ngFor=\"let article of detail.articles\">\n                        <div class=\"content\">\n                            <span style=\"font-size: .9em !important; color:#9e9e9e\">{{article.date}}</span>\n                            <br>\n                            <span><i class=\"blue circle icon\"></i>{{article.headline}}</span>\n                            <div class=\"description\">\n                                <p>{{article.description}}</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/piechart/piechart-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, ElementRef, ViewChild} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {PieChartService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\nimport {startWith, switchMap} from \"rxjs/operators\";\nimport {interval} from \"rxjs\";\nimport {ConfigurationService} from \"../../services/configuration.service\";\ndeclare var jQuery: any;\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class PieChartGadgetComponent extends GadgetBase {\n\n    @ViewChild('chartOptionsSideBar_tag') chartOptionsSideBarRef: ElementRef;\n    chartOptionsSideBar:any;\n\n    // chart options\n    explodeSlices: boolean;\n    showDonut: boolean;\n    gradient: boolean;\n    showLegend: boolean;\n    showLabels: boolean;\n    legendTitle = \"Title\";\n\n    view: any[];\n    colorScheme: any = {\n        domain: ['#0d5481', '#0AFF16', '#4894FF','#F54B7D'] //todo - control color from property page\n    };\n    //////////////////\n\n    data: any[] = [];\n    subscription: any;\n    state: string;\n\n    RUN_STATE = 'run';\n    STOP_STATE = 'stop';\n    POLL_INTERVAL = 15000;\n\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _pieChartService: PieChartService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService,\n                private _configService: ConfigurationService\n    ) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun() {\n\n        /**\n         * the base class initializes the common property gadgets. Prerun gives\n         * us a chance to initialize any of the gadgets unique properties.\n         */\n        this.initializeTheRemainderOfTheProperties();\n\n        if (this.getPropFromPropertyPages('state') == this.RUN_STATE) {\n            this.run();\n        }\n    }\n\n    initializeTheRemainderOfTheProperties() {\n\n        this.explodeSlices = this.getPropFromPropertyPages('explodeSlices');\n        this.showDonut = this.getPropFromPropertyPages('showDonut');\n        this.gradient = this.getPropFromPropertyPages('gradient');\n        this.showLegend = this.getPropFromPropertyPages('showLegend');\n        this.showLabels = this.getPropFromPropertyPages('showLabels');\n\n    }\n\n\n    public run() {\n        this.clearChartData();\n        this.initializeRunState(true);\n        this.updateData(null);\n        this.saveState(this.RUN_STATE);\n\n    }\n\n    clearChartData() {\n        this.data = [];\n    }\n\n\n    public stop() {\n\n        this.stopWithoutStateSave();\n        this.saveState(this.STOP_STATE);\n    }\n\n    /**\n     * The state is being saved to allow the board to load with the last state. Also, when the gadget is moved\n     * within the board we need to carry the gadget's state along.\n     * @param state\n     */\n    public saveState(state: string) {\n\n        this.updateProperties('{\\\"state\\\":\\\"' + state + '\\\"}');\n        this.persistTheChangeInInternalState();\n\n    }\n\n    /**\n     * When the gadget is destroyed (see ngOnDestroy) there is no need to\n     * save the state. We just want to stop any API calls.\n     */\n    public stopWithoutStateSave() {\n        if (this.subscription) {\n            this.subscription.unsubscribe();\n        }\n        const data = [];\n        Object.assign(this, {data});\n        this.setStopState(false);\n\n    }\n\n    public updateData(someData: any[]) {\n        this.data.length = 0;\n\n        /**\n         * poll every 15 seconds\n         * todo - change this to a websocket\n         */\n        this.subscription = interval(this.POLL_INTERVAL).pipe(\n            startWith(0), switchMap(() => this._pieChartService.getData(this.endpointObject.address)))\n            .subscribe(data => {\n\n                    Object.assign(this, {data});\n                },\n                error => this.handleError(error));\n    }\n\n    public drillDown(data) {\n        // this._route.navigate(['/detail'], {});\n    }\n\n\n    private setInternalProperties(updatedPropsObject: any) {\n\n        this.state = updatedPropsObject.state;\n\n        if (updatedPropsObject.title != undefined) {\n\n            this.title = updatedPropsObject.title;\n            this.explodeSlices = updatedPropsObject.explodeSlices;\n            this.showDonut = updatedPropsObject.showDonut;\n            this.gradient = updatedPropsObject.gradient;\n            this.showLegend = updatedPropsObject.showLegend;\n            this.showLabels = updatedPropsObject.showLabels;\n\n            this.setEndPoint(updatedPropsObject.endpoint);\n            this.showOperationControls = true;\n        }\n    }\n\n    /**\n     * todo\n     *  This is called from the dynamic property page form or when the internal running state changes\n     *  A similar operation exists on the procmman-config-service\n     *  whenever the property page form is saved, the in memory board model\n     *  is updated as well as the gadget instance properties\n     *  which is what the code below does. This can be eliminated with code added to the\n     *  config service or the property page service.\n     *\n     * **/\n    public updateProperties(updatedProperties: any) {\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        /**\n         * update this tools property pages\n         */\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        /**\n         * update the tools internal state\n         */\n        this.setInternalProperties(updatedPropsObject);\n\n    }\n\n    public ngOnDestroy() {\n\n        this.stopWithoutStateSave();\n    }\n\n\n    /**\n     * todo - need to improve how internal state is saved to persistant store\n     */\n    private persistTheChangeInInternalState() {\n        let payLoad =\n            \"{\\\"instanceId\\\":\" + this.instanceId\n            + \",\\\"title\\\":\\\"\" + this.title\n            + \"\\\",\\\"state\\\":\\\"\" + this.state\n            + \"\\\",\\\"endpoint\\\":\\\"\" + this.endpointObject.name\n            + \"\\\",\\\"explodeSlices\\\":\" + this.explodeSlices\n            + \",\\\"showDonut\\\":\"  + this.showDonut\n            + \",\\\"gradient\\\":\" + this.gradient\n            + \",\\\"showLegend\\\":\" + this.showLegend\n            + \",\\\"showLabels\\\":\" + this.showLabels\n            + \"}\";\n\n        this._configService.notifyGadgetOnPropertyChange(payLoad, this.instanceId);\n\n    }\n\n    toggleChartProperties() {\n\n        if(this.globalOptions.displayGadgetOptionsInSideBar == false){\n            this.toggleConfigMode();\n            return;\n        }\n        this.chartOptionsSideBar = jQuery(this.chartOptionsSideBarRef.nativeElement);\n        this.chartOptionsSideBar.sidebar('setting', 'transition', 'overlay');\n        this.chartOptionsSideBar.sidebar('toggle');\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/piechart/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\n\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class PieChartService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    getData(endpoint: string) {\n        return this._http.get(endpoint)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/piechart/view.html",
    "content": "<div class=\"ui  center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleChartProperties()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig\" style=\"max-height: 300px; max-width: 400px; min-height: 300px\">\n                <ngx-charts-pie-chart\n                        *ngIf=\"!inConfig\"\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [legend]=\"showLegend\"\n                        [explodeSlices]=\"explodeSlices\"\n                        [labels]=\"showLabels\"\n                        [doughnut]=\"showDonut\"\n                        [gradient]=\"gradient\"\n                        [legendTitle]=\"legendTitle\"\n                        [arcWidth]=\".5\"\n                        (select)=\"drillDownPopUp.showDrillDownDetail($event)\">\n                </ngx-charts-pie-chart>\n            </div>\n        </div>\n    </div>\n\n    <!-- use the side bar content -->\n    <div *ngIf=\"globalOptions.displayGadgetOptionsInSideBar == true\" class=\"ui sidebar left vertical menu\" #chartOptionsSideBar_tag>\n        <br>\n        <div class=\"ct-title\">{{title}}</div>\n        <br>\n        <app-dynamic-form\n                [gadgetTags]=\"gadgetTags\"\n                [propertyPages]=\"propertyPages\"\n                [instanceId]=\"instanceId\"\n                (updatePropertiesEvent)=\"updateProperties($event)\">\n        </app-dynamic-form>\n    </div>\n\n\n    <app-dynamic-form *ngIf=\"inConfig && globalOptions.displayGadgetOptionsInSideBar == false\"\n                      [gadgetTags]=\"gadgetTags\"\n                      [propertyPages]=\"propertyPages\"\n                      [instanceId]=\"instanceId\"\n                      (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/gadgets/port-connection/port-connection-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, OnDestroy} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {ConnectionService} from './service';\nimport {EndPointModel} from \"./service.model\";\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n\n\n})\nexport class PortConnectionGadgetComponent extends GadgetBase implements OnDestroy {\n\n    host: string;\n    port: string;\n    endPoints: Array<any> = [];\n    testResultData: Array<any> = [];\n    topic: any;\n\n    constructor(protected _procMonRuntimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                protected _connectionService: ConnectionService,\n                protected _optionsService: OptionsService) {\n        super(_procMonRuntimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun(): void {\n        this.port = this.getPropFromPropertyPages('port');\n        this.host = this.getPropFromPropertyPages('host');\n        this.setTopic();\n    }\n\n    public run() {\n        /** todo - add a one second delay to give the appearance\n         *  of something happening when there are two subsequent tests that\n         *  have the same result\n         */\n        this.setUpEndPoints();\n        this.initializeRunState(false);\n        this.testConnection();\n        this.inRun = true;\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public testConnection() {\n\n        const me = this;\n\n        /**\n         * todo:refactor - the requests that include multiple ports are submitted in a loop to avoid requests who's host will\n         * fail due to a timeout. If there are multiple endpoints being tested at the same time\n         * an accumulation of timeouts will exceed the 30 second connection response window that when hit\n         * will result in a 503 from the server.\n         */\n        this.endPoints.forEach(function (endpoint) {\n\n            let endpointInstance = [];\n            endpointInstance.push(endpoint);\n\n            /**\n             * todon- consider adding a bit of delay between requests\n             */\n            me._connectionService.testConnectivity(endpointInstance).subscribe(\n                data => {\n\n                    me.testResultData.push(...data);\n                    me.stop();\n\n                },\n                error => me.handleError(error));\n        });\n    }\n\n    private clearState() {\n        this.testResultData.length = 0;\n        this.endPoints.length = 0;\n    }\n\n    public updateData(data: any[]) {\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n                    }\n                }\n            }\n        });\n\n\n        this.port = updatedPropsObject.port;\n        this.host = updatedPropsObject.host;\n        this.title = updatedPropsObject.title;\n        this.showOperationControls = true;\n\n    }\n\n    public setUpEndPoints() {\n\n        this.clearState();\n\n        let ports: Array<string>;\n\n        ports = this.port.split(\",\");\n\n        const me = this;\n\n        ports.forEach(function (port) {\n\n            me.endPoints.push(new EndPointModel(me.host.trim(), port.trim()));\n\n        });\n\n    }\n\n    public setTopic() {\n\n            this.topic = {\n                \"concept\": {\n                    \"id\": \"c_network_test_tool\",\n                    \"xml:lang\": \"en-us\",\n                    \"title\": \"Network Test Connectivity Tool\",\n                    \"shortdesc\": \"The Network Test Connectivity tool tests host addresses and ports to determine if a connection can be established. If a connection can be established, the tool returns a green checkmark. If a connection cannot be established, the raw error condition displays, along with possible causes and actions.\",\n                    \"conbody\": {\n                        \"p\": [\n                            \"The Network Test Connectivity tool can provide guidance for the following error conditions:\",\n                            {\n                                \"ul\": {\n                                    \"id\": \"ul_k5c_qdl_r2b\",\n                                    \"li\": [\n                                        \"time out\",\n                                        \"connection refused\",\n                                        \"unknown host\",\n                                        \"no route\",\n                                        \"unreachable host\"\n                                    ]\n                                }\n                            }\n                        ]\n                    }\n                }\n            }\n\n    }\n\n    ngOnDestroy() {\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/port-connection/port-connection.css",
    "content": ".input-width{\n    width:45%\n}"
  },
  {
    "path": "src/app/gadgets/port-connection/result-view.component.ts",
    "content": "\nimport {Component, Input} from \"@angular/core\";\nimport {animate, style, transition, trigger} from \"@angular/animations\";\n\n@Component({\n    selector: 'connection-result-view-component',\n    moduleId: module.id,\n    templateUrl: './result-view.html',\n    styleUrls: ['../_common/styles-gadget.css'],\n    animations: [\n\n        trigger(\n            'fade',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(1000, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(300, style({opacity: 0}))\n                ])\n            ])\n    ]\n\n})\nexport class ResultViewComponent{\n\n\n    @Input() connectionResult: any;\n\n    detailMessageOpen = false;\n\n\n    public toggleMessageDetail(): void {\n\n        this.detailMessageOpen = !this.detailMessageOpen;\n\n    }\n\n}"
  },
  {
    "path": "src/app/gadgets/port-connection/result-view.html",
    "content": "<div class=\"ui centered grid\">\n    <div class=\"ui basic segment\">\n        <table class=\" ui compact unstackable fixed table\" style=\"border:none !important;\">\n            <th>\n                Host\n            </th>\n            <th>\n                Port\n            </th>\n            <th>\n                Description\n            </th>\n            <th style=\"float:right\">\n                Status\n            </th>\n            <tr>\n                <td>\n                    {{connectionResult.host}}\n                </td>\n                <td>\n                    {{connectionResult.port}}\n                </td>\n                <td>\n                    {{connectionResult.portDescription}}\n                </td>\n                <td>\n                    <i class=\"icon large\"\n                       [ngClass]=\"{\n\n                            'green':connectionResult.status == 'success',\n                            'check':connectionResult.status == 'success',\n                            'yellow':connectionResult.status != 'success',\n                            'exclamation triangle':connectionResult.status != 'success'\n                            }\" style=\"float:right\"></i>\n                </td>\n            </tr>\n\n            <tr [@fade] *ngIf=\"connectionResult.status != 'success'\">\n                <td colspan=\"4\">\n                    <div class=\"ui info message full-width\">\n                        <div>\n                            {{connectionResult.exception}}\n                        </div>\n\n                    </div>\n                </td>\n            </tr>\n\n            <tr [@fade] *ngIf=\"connectionResult.status != 'success'\">\n                <td colspan=\"4\" [@fade] *ngIf=\"detailMessageOpen == true\">\n                    <div>\n                        <table class=\"ui celled fixed unstackable table\" style=\"border:none !important\">\n                            <thead>\n                            <tr>\n                                <th>Possible causes</th>\n                                <th>Actions you can take</th>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr *ngFor=\"let solution of connectionResult.knowledgeBaseArticle.solution\">\n                                <td>{{solution.cause}}</td>\n                                <td>\n                                    <ul *ngFor=\"let action of solution.action\">\n                                        <li>{{action.task}}</li>\n                                    </ul>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                    </div>\n                    <!-- <solution-view-component></solution-view-component> -->\n                </td>\n            </tr>\n        </table>\n\n    </div>\n    <div class=\"ui bottom right attached label\" style=\"background-color: transparent\">\n        <i *ngIf=\"connectionResult.status != 'success'\" class=\"large chevron icon\" (click)=\"toggleMessageDetail()\"\n           [ngClass]=\"{'up':detailMessageOpen == true, 'down': detailMessageOpen == false}\"\n           style=\"color:lightgrey\">\n        </i>\n    </div>\n</div>\n\n\n\n"
  },
  {
    "path": "src/app/gadgets/port-connection/service.model.ts",
    "content": "\nexport class EndPointModel {\n\n    host: string;\n    port: string;\n\n    constructor(host: string, port: string) {\n\n        this.host = host;\n        this.port = port;\n\n    }\n}"
  },
  {
    "path": "src/app/gadgets/port-connection/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient, HttpHeaders} from '@angular/common/http';\nimport {EndPointModel} from \"./service.model\";\nimport {environment} from \"../../../environments/environment\";\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class ConnectionService {\n\n    connectivityTestURL: string;\n\n    constructor(private _http: HttpClient) {\n        this.configure();\n    }\n\n    /**\n     * TODO - the connectivityTestURL should be based on the Endpoint object that currently\n     * comes from the board configuration. However, in order for this to be more modular\n     * the Endpoint object should be managed by the gadget config form. The URL, when run in production mode, is\n     * currently assumes to be the microservice jar file that runs the framework. The GUI should allow\n     * the user to define whether the URL is internal or remote.\n     */\n    configure() {\n\n        if (environment.production) {\n            /**\n             * todo - consider setting this value if a user checks and option in the gadget's form\n             * that indicate the user elects to use the interal api call.\n             */\n\n            this.connectivityTestURL = '/connectTest';\n        } else {\n            /**\n             * todo - consider sett this from the gadget form\n             */\n\n            this.connectivityTestURL = 'http://localhost:8080/connectTest';\n        }\n\n    }\n\n    testConnectivity(endPoints: Array<EndPointModel>) {\n\n        const httpOptions = {\n            headers: new HttpHeaders({\n                'Content-Type': 'application/json',\n                'Accept':'application/json'\n            })\n        };\n        return this._http.post<Array<EndPointModel>>(this.connectivityTestURL, endPoints, httpOptions)\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/port-connection/solution-view.component.ts",
    "content": "import {Component, Input} from \"@angular/core\";\n\n\n@Component({\n    selector: 'solution-view-component',\n    moduleId: module.id,\n    templateUrl: './solution-view.html',\n    styleUrls: ['./port-connection.css']\n\n\n})\nexport class SolutionViewComponent {\n\n}"
  },
  {
    "path": "src/app/gadgets/port-connection/solution-view.html",
    "content": "\n<div class=\"ui basic segment full-width\">\n\n    <div class=\"grid-row\">\n        <mat-form-field class=\"input-width\">\n            <input  matInput placeholder=\"Add cause\">\n        </mat-form-field>\n        <mat-form-field class=\"input-width\">\n            <input  matInput placeholder=\"Add solution\">\n        </mat-form-field>\n            <mat-icon>add</mat-icon>\n    </div>\n\n</div>\n"
  },
  {
    "path": "src/app/gadgets/port-connection/view.html",
    "content": "<div class=\"ui left aligned segment gadget\" dnd-draggable [dragEnabled]=\"true\"\n     [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\" style=\"background-color:#f7f7f7\">\n\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\"\n            (helpEvent)=\"helpModal.showHelp()\">>\n    </app-gadget-header>\n\n    <div *ngIf=\"!inConfig\">\n        <div class=\"ui basic segment\">\n            <div class=\"ui header\">\n                Testing Host & Port(s)\n            </div>\n            <p>{{host}} {{port}}</p>\n        </div>\n    </div>\n    <br>\n    <div class=\"ui  centered grid\" *ngIf=\"!inConfig\" style=\"background-color:#f7f7f7\">\n\n        <div class=\"ui segment\" *ngFor=\"let result of testResultData\">\n\n            <connection-result-view-component [connectionResult]=\"result\"></connection-result-view-component>\n\n        </div>\n        <br>\n    </div>\n\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                      [gadgetTags]=\"gadgetTags\"\n                      [propertyPages]=\"propertyPages\"\n                      [instanceId]=\"instanceId\"\n                      (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-help-modal #helpModal [topic]=\"topic\"></app-help-modal>\n\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <div class=\"ui bottom attached\" *ngIf=\"actionInitiated\" style=\"width:25%\">\n        <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n    </div>\n    <br>\n\n</div>\n"
  },
  {
    "path": "src/app/gadgets/property-list/property-list-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component, OnDestroy} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\nexport class PropertyListGadgetComponent extends GadgetBase implements OnDestroy {\n\n\n    gadgetHasOperationControls = false;\n    showConfigurationControl = false;\n\n    constructor(protected _procMonRuntimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService) {\n        super(_procMonRuntimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun(): void {\n    }\n\n    public run() {\n        this.initializeRunState(true);\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        this.showOperationControls = true;\n    }\n\n    ngOnDestroy() {\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/property-list/view.html",
    "content": "\n    <div class=\"ui left aligned segment gadget\" dnd-draggable [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n        <app-gadget-header\n                (mouseover)=\"showGadgetControls(true)\"\n                (mouseleave)=\"showGadgetControls(false)\"\n                [globalOptions]=\"globalOptions\"\n                [title]=\"title\"\n                [inRun]=\"inRun\"\n                [inConfig]=\"inConfig\"\n                [actionInitiated]=\"actionInitiated\"\n                [showOperationControls]=\"showOperationControls\"\n                [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n                [showConfigurationControl]=\"showConfigurationControl\"\n                [showControls]=\"showControls\"\n                (toggleConfigModeEvent)=\"toggleConfigMode()\"\n                (removeEvent)=\"remove()\"\n                (runEvent)=\"run()\"\n                (stopEvent)=\"stop()\">\n        </app-gadget-header>\n\n        <div class=\"ui mini form\" style=\"min-height: 275px\">\n            <div class=\"fields\">\n                <div class=\"sixteen wide field\">\n                    <label>Job Manager Task Executor Pool Size</label>\n                    <input placeholder=\"Adjust how many jobs should run at the same time\" type=\"number\" value=\"5000\">\n                </div>\n            </div>\n            <div class=\"fields\">\n                <div class=\"sixteen wide field\">\n                    <label>Job Manager Threads Per Node</label>\n                    <input placeholder=\"Increase the amount of memory the system uses\" type=\"number\" value=\"500\">\n                </div>\n            </div>\n            <div class=\"fields\">\n                <div class=\"sixteen wide field\">\n                    <label>Job Manager Threads Per Job</label>\n                    <input placeholder=\"Adjust how many jobs should run at the same time\" type=\"number\" value=\"500\">\n                </div>\n            </div>\n        </div>\n        <div style=\"clear:both; text-align: center\">\n            <i class=\"link big orange circular refresh icon\"></i>\n        </div>\n    </div>\n"
  },
  {
    "path": "src/app/gadgets/service-list/service-list-gadget.component.ts",
    "content": "import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';\nimport {\n    style, trigger, animate, transition\n} from '@angular/animations';\n\nimport {RuntimeService} from '../../services/runtime.service';\nimport {serviceList} from './service-list';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css'],\n    animations: [\n        trigger(\n            'showHideAnimation',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(1000, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(1000, style({opacity: 0}))\n\n                ])\n            ])]\n})\nexport class ServiceListGadgetComponent extends GadgetBase implements OnDestroy {\n\n    // todo just realy on json\n    serviceList: {\n        active: boolean,\n        applicationName: string,\n        description: string,\n        icon: string,\n        pseudoName: string,\n        processId: string }[] = [];\n\n    constructor(protected _procMonRuntimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                private _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService) {\n        super(_procMonRuntimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n       this.run();\n\n    }\n\n    public preRun(): void {\n    }\n\n    public run() {\n        this.initializeRunState( true);\n        Object.assign(this, {serviceList});\n\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/service-list/service-list.ts",
    "content": "/**\n * Created by jayhamilton on 1/28/17.\n */\nexport const serviceList: {\n    active: boolean,\n    applicationName: string,\n    description: string,\n    icon: string,\n    pseudoName: string,\n    processId: string}[] = [\n    {\n        active: false,\n        applicationName: 'Application Container',\n        description: 'This is a modular application container.',\n        icon: 'images/donut.png',\n        pseudoName: 'Virgo',\n        processId: '1'\n    },\n    {\n        active: false,\n        applicationName: 'Microservice Discover Server',\n        description: 'This is a microservice discovery service.',\n        icon: 'images/donut.png',\n        pseudoName: 'Eureka',\n        processId: '2'\n    },\n    {\n        active: false,\n        applicationName: 'Relational Database Management System',\n        description: 'This is a database server.',\n        icon: 'images/donut.png',\n        pseudoName: 'Postgres',\n        processId: '3'\n    },\n    {\n        active: false,\n        applicationName: 'NO Sql Database Server',\n        description: 'This is a no sql database server.',\n        icon: 'images/donut.png',\n        pseudoName: 'Mongo',\n        processId: '4'\n    }\n\n];\n"
  },
  {
    "path": "src/app/gadgets/service-list/view.html",
    "content": "<div  class=\"ui segment left aligned gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui divided selection list\" *ngIf=\"!inConfig\" style=\"min-height: 250px\">\n        <div *ngFor=\"let serviceItem of serviceList\" class=\"item\">\n\n            <div class=\"left floated content\">\n               <i *ngIf=\"serviceItem.processId\" [@showHideAnimation] class=\"big green check icon\"></i>\n                <i *ngIf=\"serviceItem.processId==''\" [@showHideAnimation] class=\"big red minus circle\"></i>\n            </div>\n            <div class=\"content\">\n                <a class=\"header\">{{serviceItem.applicationName}} - {{serviceItem.pseudoName}}</a>\n                {{serviceItem.description}}\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/statistic/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n@Injectable()\nexport class StatisticService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get(resourceType) {\n        return this._http.get('/assets/api/stat-' + resourceType + '-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/statistic/statistic-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {StatisticService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\nexport class StatisticGadgetComponent extends GadgetBase {\n\n    gadgetHasOperationControls = false;\n\n    // runtime document subscription\n    data: any;\n    resource: string;\n\n    constructor(protected _statisticService: StatisticService,\n                protected _procMonRuntimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService) {\n        super(_procMonRuntimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n        this.run();\n    }\n\n    public preRun(): void {\n        this.resource = this.getPropFromPropertyPages('resource');\n        this.updateData(null);\n    }\n\n    public run() {\n        this.data = [];\n        this.initializeRunState(true);\n        this.updateData(null);\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n        this._statisticService.get(this.resource).subscribe(data => {\n                this.data = data;\n            },\n            error => this.handleError(error));\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.resource = updatedPropsObject.resource;\n        this.title = updatedPropsObject.title;\n        this.setEndPoint(updatedPropsObject.endpoint);\n        this.updateData(null);\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/statistic/view.html",
    "content": "<div class=\"ui center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div class=\"ui grey small statistic\"  *ngIf=\"!inConfig\">\n        <div class=\"value\">\n            {{data.total}}&nbsp;&nbsp;<i class=\" {{data.color}}  {{data.icon}} \"></i>\n        </div>\n        <div class=\"label\">\n            <span style=\"color:grey\">{{data.name}}</span>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/storage-object-list/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17.\n */\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n@Injectable()\nexport class StorageService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get() {\n        return this._http.get('/assets/api/storage-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/storage-object-list/storage-object-list.component.ts",
    "content": "import {ChangeDetectorRef, Component} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {StorageService} from './service';\nimport {animate, style, transition, trigger} from '@angular/animations';\nimport {Facet} from '../../facet/facet-model';\nimport {FacetTagProcessor} from '../../facet/facet-tag-processor';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./style.css'],\n    animations: [\n        trigger(\n            'showHideAnimation',\n            [\n                transition(':enter', [   // :enter is alias to 'void => *'\n                    style({opacity: 0}),\n                    animate(750, style({opacity: 1}))\n                ]),\n                transition(':leave', [   // :leave is alias to '* => void'\n                    animate(750, style({opacity: 0}))\n                ])\n            ])\n    ]\n})\nexport class StorageObjectListComponent extends GadgetBase {\n\n    // runtime document subscription\n    news: any;\n    resource: string;\n    objectList: any[] = [];\n    facetTags: Array<Facet>;\n    objectTitleList: string[] = [];\n    placeHolderText = 'Enter volume search string';\n    layoutColumnOneWidth = 'four';\n    layoutColumnTwoWidth = 'twelve';\n\n\n    gadgetHasOperationControls = false;\n\n    constructor(protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _storageService: StorageService,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n    }\n\n    public preRun(): void {\n        this.updateData(null);\n\n        this.run();\n    }\n\n    public run() {\n        this.news = [];\n        this.initializeRunState( true);\n        this.updateData(null);\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n        this._storageService.get().subscribe(item => {\n                item['volumes'].forEach(_data => {\n                    this.objectList.push(_data);\n                    this.objectTitleList.push(_data.name);\n                });\n                const facetTagProcess = new FacetTagProcessor(this.objectList);\n                this.facetTags = facetTagProcess.getFacetTags();\n            },\n            error => this.handleError(error));\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.setEndPoint(updatedPropsObject.endpoint);\n        this.updateData(null);\n    }\n\n    actionHandler(actionItem, actionName) {\n\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/storage-object-list/style.css",
    "content": ".storage{\n    overflow-y:hidden;\n    overflow-x:hidden;\n    padding-right:5px;\n    padding-left:5px;\n    height:100%;\n    min-height: 275px;\n    text-align: left !important;\n    background-color:#f7f7f7\n}\n\n.chartLabel{\n    font-family: Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;\n    background-color: white;\n    font-size: 1em;\n    font-weight: normal;\n    color: grey;\n    text-align: center;\n}\n.ui.statistic>.label, .ui.statistics .statistic>.label{\n\n    font-weight: normal;\n    text-transform: none;\n}"
  },
  {
    "path": "src/app/gadgets/storage-object-list/view.html",
    "content": "<div  class=\"ui center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\"\n     style=\"background-color: #f7f7f7\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"heart icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n    <div *ngIf=\"!inConfig\" class=\"storage\">\n        <app-data-list\n\n                [objectTitleList]=\"objectTitleList\"\n                [objectList]=\"objectList\"\n                [facetTags]=\"facetTags\"\n                [placeHolderText]=\"placeHolderText\"\n                [layoutColumnOneWidth]=\"layoutColumnOneWidth\"\n                [layoutColumnTwoWidth]=\"layoutColumnTwoWidth\">\n\n            <ng-template let-item=\"$implicit\">\n\n                <div [@showHideAnimation] class=\"ui padded segment\" style=\"background-color:white;\">\n                    <div class=\"ui large middle aligned divided list\">\n                        <div class=\"item\">\n                            <div class=\"right floated content\">\n                                <a *ngIf=\"item.actions.length == 1\"\n\n                                   routerLink=\".\"\n                                   (click)=\"actionHandler(item, item.actions[0].name)\">\n                                    <span style=\"color:darkgrey; font-size:2em\">...</span>\n                                </a>\n\n                            </div>\n                            <div class=\"left floated content\">\n                                <div class=\"ui stackable centered grid\">\n                                    <div class=\"column\">\n                                        <div class=\"row\">\n                                            <div class=\"chartLabel\">VOLUME</div>\n                                            <img class=\"ui centered image\" src=\"{{item.icon}}\">\n                                            {{item.volumeId}}\n                                        </div>\n                                        <div class=\"row\">\n                                            <br>\n                                            <button *ngFor=\"let tag of item.tags\" class=\"ui basic gray compact button\">\n                                                {{tag.name}}\n                                            </button>\n                                        </div>\n                                    </div>\n                                </div>\n                            </div>\n                            <div class=\"ui stackable sixteen wide grid\">\n                                <div class=\"row\">\n                                    <div class=\"one wide column\"></div>\n                                    <div class=\"seven wide column\">\n                                        <div class=\"ui green indicating progress\" data-value=\"25\" data-total=\"200\">\n                                            <div class=\"bar\">\n                                                <div class=\"progress\"></div>\n                                            </div>\n                                            <div class=\"chartLabel\">Used Storage</div>\n                                        </div>\n                                    </div>\n                                    <div class=\"seven wide column\">\n                                        <div class=\"row\">\n                                            <div class=\"ui grey mini statistic\">\n\n                                                <div class=\"value\">\n                                                    <i class=\"purple camera icon\"></i>&nbsp;&nbsp;&nbsp;{{item.snapshotCount}}\n                                                </div>\n                                                <div class=\"label\">\n                                                    <span style=\"color:grey\">Snapshots</span>\n                                                </div>\n                                            </div>\n                                        </div>\n                                    </div>\n                                </div>\n                                <div class=\"row\">\n                                    <div class=\"one wide column\"></div>\n                                    <div class=\"seven wide column\">\n                                        <div class=\"ui grey mini statistic\">\n\n                                            <div class=\"value\">\n                                                <i class=\"blue server icon\"></i>&nbsp;&nbsp;&nbsp;{{item.vmCount}}\n                                            </div>\n                                            <div class=\"label\">\n                                                <span style=\"color:grey\">Virtual Machines</span>\n                                            </div>\n                                        </div>\n                                    </div>\n                                    <div class=\"seven wide column\">\n                                        <div class=\"ui grey mini statistic\">\n\n                                            <div class=\"value\">\n                                                <i class=\"orange file outline icon\"></i>&nbsp;&nbsp;&nbsp;{{item.fileCount}}\n                                            </div>\n                                            <div class=\"label\">\n                                                <span style=\"color:grey\">Files</span>\n                                            </div>\n                                        </div>\n                                    </div>\n                                </div>\n                            </div>\n\n                        </div>\n                    </div>\n                </div>\n            </ng-template>\n\n        </app-data-list>\n\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                      [gadgetTags]=\"gadgetTags\"\n                      [propertyPages]=\"propertyPages\"\n                      [instanceId]=\"instanceId\"\n                      (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/todo/service.ts",
    "content": "/**\n * Created by jayhamilton on 6/24/17. Todo Service\n */\nimport {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n@Injectable()\nexport class TodoService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get() {\n        return this._http.get('/assets/api/todo-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/todo/todo-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {TodoService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";  // todo component\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\nexport class TodoGadgetComponent extends GadgetBase {\n\n    gadgetHasOperationControls = false;\n\n    // runtime document subscription\n    data: any;\n    todo: string;\n    todoList = ['todo 1'];\n\n    constructor(protected _todoService: TodoService,\n                protected _procMonRuntimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService) {\n        super(_procMonRuntimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n    }\n\n    public preRun(): void {\n        this.run();\n    }\n\n    public run() {\n        this.data = [];\n        this.initializeRunState(true);\n        this.updateData(null);\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n        this._todoService.get().subscribe(_data => {\n                this.data = _data;\n            },\n            error => this.handleError(error));\n    }\n\n    public addTodo(todo: string) {\n        this.todoList.push(todo);\n    }\n\n    public removeTodo(todoIx: number) {\n        if (this.todoList.length) {\n            this.todoList.splice(todoIx, 1);\n        }\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.setEndPoint(updatedPropsObject.endpoint);\n        this.updateData(null);\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/todo/view.html",
    "content": "<!--todo view -->\n<div class=\"ui center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <app-gadget-header (mouseover)=\"showGadgetControls(true)\"\n                       (mouseleave)=\"showGadgetControls(false)\"\n                       [globalOptions]=\"globalOptions\"\n                       [title]=\"title\"\n                       [inRun]=\"inRun\"\n                       [inConfig]=\"inConfig\"\n                       [actionInitiated]=\"actionInitiated\"\n                       [showOperationControls]=\"showOperationControls\"\n                       [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n                       [showConfigurationControl]=\"showConfigurationControl\"\n                       [showControls]=\"showControls\"\n                       (toggleConfigModeEvent)=\"toggleConfigMode()\"\n                       (removeEvent)=\"remove()\"\n                       (runEvent)=\"run()\"\n                       (stopEvent)=\"stop()\">\n    </app-gadget-header>\n\n\n    <div class=\"card\" *ngIf=\"!inConfig\">\n        <div class=\"content\">\n            <div class=\"description\">\n                <i class=\"big thumbs up outline icon\"></i> This is a very simple todo gadget!\n                <br>\n                Todo service mock data:<span style=\"color:#0f9119\"> {{data.value}} </span>\n            </div>\n        </div>\n    </div>\n    <table class=\"ui very basic table\" *ngIf=\"!inConfig\">\n        <thead>\n        <th class=\"c-col\">#</th>\n        <th>Item</th>\n        <th></th>\n        </thead>\n        <tr class=\"ui basic segment\" *ngFor=\"let todo of todoList; let i = index\">\n            <td class=\"c-col\">{{i + 1}}</td>\n            <td>{{todo}}</td>\n            <td style=\"text-align:right\">\n                <a mat-mini-fab routerLink=\".\" (click)=\"removeTodo(i)\">\n                    <mat-icon>clear</mat-icon>\n                </a>\n            </td>\n        </tr>\n        <tr>\n            <td></td>\n            <td>\n                <mat-form-field>\n                    <input [(ngModel)]=\"todo\" matInput placeholder=\"Add Todo\">\n                </mat-form-field>\n            </td>\n            <td style=\"text-align:right\">\n                <a mat-mini-fab routerLink=\".\" color='primary' (click)=\"addTodo(todo)\">\n                    <mat-icon>add</mat-icon>\n                </a>\n            </td>\n        </tr>\n    </table>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                      [gadgetTags]=\"gadgetTags\"\n                      [propertyPages]=\"propertyPages\"\n                      [instanceId]=\"instanceId\"\n                      (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n</div>\n\n"
  },
  {
    "path": "src/app/gadgets/trend/service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n@Injectable()\nexport class TrendService {\n\n    constructor(private _http: HttpClient) {\n    }\n\n    get() {\n        return this._http.get('/assets/api/trend-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/trend/trend-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {TrendService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\ndeclare var d3: any;\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class TrendGadgetComponent extends GadgetBase {\n\n    // chart options\n    showXAxis = true;\n    showYAxis = true;\n    gradient = true;\n    showLegend = true;\n    showXAxisLabel = true;\n    showYAxisLabel = true;\n    yAxisLabel = 'Trend Data';\n    xAxisLabel = 'Trend Time Line';\n    view: any[];\n    data: any[] = [];\n    colorScheme: any = {\n        domain: ['#7B7E81', '#0AFF16', '#FAFF16']\n    };\n\n    d3 = d3;\n\n    constructor(protected _trendService: TrendService,\n                protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n    }\n\n    public preRun(): void {\n\n        this.run();\n    }\n\n    public run() {\n        this.data = [];\n        this.initializeRunState( true);\n        this.updateData(null);\n    }\n\n    public stop() {\n        this.setStopState(false);\n    }\n\n    public updateData(data: any[]) {\n\n        this._trendService.get().subscribe(res => {\n                this.data = res['data'];\n            },\n            error => this.handleError(error));\n    }\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.showXAxis = updatedPropsObject.chart_properties;\n        this.showYAxis = updatedPropsObject.chart_properties;\n        this.gradient = updatedPropsObject.chart_properties;\n        this.showLegend = updatedPropsObject.chart_properties;\n        this.showXAxisLabel = updatedPropsObject.chart_properties;\n        this.showYAxisLabel = updatedPropsObject.chart_properties;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/trend/view.html",
    "content": "<div class=\"ui center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"circle icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\"\n            (helpEvent)=\"helpModal.showHelp()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig\" style=\"min-height: 275px\">\n                <ngx-charts-area-chart\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"data\"\n                        [gradient]=\"gradient\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [autoScale]=\"autoScale\"\n                        [curve]=\"d3.curveCatmullRom\"\n                        (select)=\"drillDownPopUp.showDetail($event)\">\n                </ngx-charts-area-chart>\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n    <app-help-modal #helpModal></app-help-modal>\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/gadgets/trend-line/service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {Observable, timer} from 'rxjs';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {HttpClient} from '@angular/common/http';\nimport {catchError} from \"rxjs/operators\";\n\n@Injectable()\nexport class TrendLineService {\n    static seedData() {\n\n        const array = [];\n        for (let i = 0; i < 25; i++) {\n            array.push({\n                'name': i.toString(),\n                'value': 0\n            });\n        }\n        return array;\n    }\n    static retrieveData() {\n\n        const currentDate = new Date();\n        const time = TrendLineService.getDay(\n            currentDate.getDay()) + ':' +\n            currentDate.getHours() + ':' +\n            currentDate.getMinutes() + ':' +\n            currentDate.getSeconds();\n\n        return {\n\n            'name': time,\n            'value': TrendLineService.getRandomArbitrary(5, 20)\n        };\n\n    }\n    static getRandomArbitrary(min, max) {\n        return Math.round(Math.random() * (max - min) + min);\n    }\n    static getDay(dayOfWeek: number) {\n\n        switch (dayOfWeek) {\n            case 0:\n                return 'sun';\n            case 1:\n                return 'mon';\n            case 2:\n                return 'tue';\n            case 3:\n                return 'wed';\n            case 4:\n                return 'thur';\n            case 5:\n                return 'fri';\n            case 6:\n                return 'sat';\n        }\n    }\n    constructor(private _http: HttpClient) {\n    }\n\n    public get(collectors: any[]) {\n        return new Observable(observer => {\n            timer(500, 5000).subscribe(t => {\n\n                const data = [];\n                collectors.forEach(collector => {\n                    data.push(TrendLineService.retrieveData());\n                });\n\n                observer.next(data);\n            });\n        });\n    }\n\n    public stop(subscription: any) {\n        subscription.unsubscribe();\n    }\n\n    getHelpTopic() {\n\n        return this._http.get('/assets/api/trendline-help-model.json')\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n\n    }\n}\n"
  },
  {
    "path": "src/app/gadgets/trend-line/trend-line-gadget.component.ts",
    "content": "import {ChangeDetectorRef, Component} from '@angular/core';\nimport {GadgetInstanceService} from '../../grid/grid.service';\nimport {RuntimeService} from '../../services/runtime.service';\nimport {GadgetPropertyService} from '../_common/gadget-property.service';\nimport {EndPointService} from '../../configuration/tab-endpoint/endpoint.service';\nimport {GadgetBase} from '../_common/gadget-base';\nimport {TrendLineService} from './service';\nimport {OptionsService} from \"../../configuration/tab-options/service\";\n\ndeclare var d3: any;\n\n@Component({\n    selector: 'app-dynamic-component',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['../_common/styles-gadget.css']\n})\n\nexport class TrendLineGadgetComponent extends GadgetBase {\n\n\n    topic: any;\n\n    // chart options\n    showXAxis  = true;\n    showYAxis  = true;\n    gradient  = true;\n    showLegend  = true;\n    showXAxisLabel  = true;\n    showYAxisLabel  = true;\n    yAxisLabel  = 'IOPS';\n    xAxisLabel  = 'Time';\n    autoScale = true;\n    view: any[];\n    colorScheme: any = {\n        domain: ['#2185D0', '#0AFF16']\n    };\n\n    d3 = d3;\n    multi: any[] = [];\n\n    collectors: Array<string> = [];\n\n    eventTimerSubscription: any;\n\n    constructor(protected _trendLineService: TrendLineService,\n                protected _runtimeService: RuntimeService,\n                protected _gadgetInstanceService: GadgetInstanceService,\n                protected _propertyService: GadgetPropertyService,\n                protected _endPointService: EndPointService,\n                protected _changeDetectionRef: ChangeDetectorRef,\n                protected _optionsService: OptionsService) {\n        super(_runtimeService,\n            _gadgetInstanceService,\n            _propertyService,\n            _endPointService,\n            _changeDetectionRef,\n            _optionsService);\n\n\n    }\n\n\n    public preRun(): void {\n\n        this.setHelpTopic();\n        /**\n         * todo - get collectors from property page data\n         * @type {[string,string]}\n         */\n        this.collectors = ['read', 'write'];\n\n        for (let y = 0; y < this.collectors.length; y++) {\n\n            this.multi[y] = {\n                'name': this.collectors[y],\n                'series': TrendLineService.seedData()\n            };\n        }\n    }\n\n    public run() {\n        this.initializeRunState(true);\n        this.updateData();\n\n    }\n\n    public stop() {\n        this.setStopState(false);\n        this._trendLineService.stop(this.eventTimerSubscription);\n    }\n\n    public updateData() {\n\n        this.eventTimerSubscription = this._trendLineService.get(this.collectors).subscribe(data => {\n\n                for (let x = 0; x < this.collectors.length; x++) {\n\n                    this.multi[x].series.shift();\n                    this.multi[x].series.push(data[x]);\n\n                }\n\n                this.multi = [...this.multi];\n            },\n            error => this.handleError(error));\n    }\n\n\n    public updateProperties(updatedProperties: any) {\n\n        /**\n         * todo\n         *  A similar operation exists on the procmman-config-service\n         *  whenever the property page form is saved, the in memory board model\n         *  is updated as well as the gadget instance properties\n         *  which is what the code below does. This can be eliminated with code added to the\n         *  config service or the property page service.\n         *\n         * **/\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        this.propertyPages.forEach(function (propertyPage) {\n\n\n            for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                for (const prop in updatedPropsObject) {\n                    if (updatedPropsObject.hasOwnProperty(prop)) {\n                        if (prop === propertyPage.properties[x].key) {\n                            propertyPage.properties[x].value = updatedPropsObject[prop];\n                        }\n\n                    }\n                }\n            }\n        });\n\n        this.title = updatedPropsObject.title;\n        this.showXAxis = updatedPropsObject.chart_properties;\n        this.showYAxis = updatedPropsObject.chart_properties;\n        this.gradient = updatedPropsObject.chart_properties;\n        this.showLegend = updatedPropsObject.chart_properties;\n        this.showXAxisLabel = updatedPropsObject.chart_properties;\n        this.showYAxisLabel = updatedPropsObject.chart_properties;\n\n        this.setEndPoint(updatedPropsObject.endpoint);\n\n        this.showOperationControls = true;\n\n        /**\n         * todo - adjust collectors from property page data\n         * @type {[string,string]}\n         */\n\n    }\n\n    private setHelpTopic() {\n        this._trendLineService.getHelpTopic().subscribe(data => {\n\n            this.topic = data;\n\n        });\n    }\n\n}\n"
  },
  {
    "path": "src/app/gadgets/trend-line/view.html",
    "content": "<div class=\"ui  center aligned segment gadget\" dnd-draggable\n     [dragEnabled]=\"true\" [dragData]=\"instanceId\" [dropZones]=\"['c0','c1','c2','c3','r0','r1']\">\n\n    <a class=\"ui left corner label\">\n        <i class=\"heart icon\" [ngClass]=\"{'green':inRun, 'yellow':!inRun}\"></i>\n    </a>\n\n    <app-gadget-header\n            (mouseover)=\"showGadgetControls(true)\"\n            (mouseleave)=\"showGadgetControls(false)\"\n            [globalOptions]=\"globalOptions\"\n            [title]=\"title\"\n            [inRun]=\"inRun\"\n            [inConfig]=\"inConfig\"\n            [actionInitiated]=\"actionInitiated\"\n            [showOperationControls]=\"showOperationControls\"\n            [gadgetHasOperationControls]=\"gadgetHasOperationControls\"\n            [showConfigurationControl]=\"showConfigurationControl\"\n            [showControls]=\"showControls\"\n            (toggleConfigModeEvent)=\"toggleConfigMode()\"\n            (removeEvent)=\"remove()\"\n            (runEvent)=\"run()\"\n            (stopEvent)=\"stop()\"\n            (helpEvent)=\"helpModal.showHelp()\">\n    </app-gadget-header>\n\n    <div class=\"ui grid\">\n        <div class=\"row\">\n            <div *ngIf=\"!inConfig\" style=\"min-height: 275px\">\n                <ngx-charts-line-chart\n                        [view]=\"view\"\n                        [scheme]=\"colorScheme\"\n                        [results]=\"multi\"\n                        [gradient]=\"gradient\"\n                        [xAxis]=\"showXAxis\"\n                        [yAxis]=\"showYAxis\"\n                        [legend]=\"showLegend\"\n                        [showXAxisLabel]=\"showXAxisLabel\"\n                        [showYAxisLabel]=\"showYAxisLabel\"\n                        [xAxisLabel]=\"xAxisLabel\"\n                        [yAxisLabel]=\"yAxisLabel\"\n                        [autoScale]=\"autoScale\"\n                        (select)=\"drillDownPopUp.showDetail($event)\">\n                </ngx-charts-line-chart>\n            </div>\n        </div>\n    </div>\n\n    <app-dynamic-form *ngIf=\"inConfig\"\n                  [gadgetTags]=\"gadgetTags\"\n                  [propertyPages]=\"propertyPages\"\n                  [instanceId]=\"instanceId\"\n                  (updatePropertiesEvent)=\"updateProperties($event)\">\n    </app-dynamic-form>\n\n    <app-error-handler\n            [errorObject]=\"errorObject\"\n            [errorExists]=\"errorExists\">\n    </app-error-handler>\n\n    <app-vis-drill-down-modal #drillDownPopUp></app-vis-drill-down-modal>\n\n    <app-help-modal #helpModal [topic]=\"topic\"></app-help-modal>\n\n    <div class=\"ui bottom attached\" *ngIf=\"actionInitiated\">\n        <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n    </div>\n\n\n</div>\n\n\n"
  },
  {
    "path": "src/app/grid/cell.component.ts",
    "content": "import {Component, Input, ViewContainerRef, OnInit, ComponentFactoryResolver} from '@angular/core';\nimport {GadgetInstanceService} from './grid.service';\nimport {GadgetFactory} from '../add-gadget/gadget-factory';\n\n/*\n this class handles the dynamic creation of components\n */\n\n@Component({\n    selector: 'app-grid-cell',\n    template: ''\n})\nexport class CellComponent implements OnInit {\n    @Input() gadgetType: string;\n    @Input() gadgetConfig: any;\n    @Input() gadgetInstanceId: number;\n    @Input() gadgetTags: Array<any>;\n\n\n    constructor(private viewContainerRef: ViewContainerRef,\n                private cfr: ComponentFactoryResolver, private gadgetInstanceService: GadgetInstanceService) {\n    }\n\n    ngOnInit() {\n        /*\n         create component instance dynamically\n         */\n        const component: any = GadgetFactory.getComponentType(this.gadgetType);\n        let compFactory: any = {};\n        let gadgetRef: any = {};\n\n        if (component) {\n            compFactory = this.cfr.resolveComponentFactory(component);\n            gadgetRef = this.viewContainerRef.createComponent(compFactory);\n\n            /*\n             we need to pass the input parameters (instance id and config) back into the newly created component.\n             */\n            gadgetRef.instance.configureGadget(this.gadgetInstanceId, this.gadgetConfig, this .gadgetTags);\n\n            /*\n             add concrete component to service for tracking\n             */\n            this.gadgetInstanceService.addInstance(gadgetRef);\n        }\n\n    }\n\n}\n\n"
  },
  {
    "path": "src/app/grid/grid.component.ts",
    "content": "import {Component, Output, EventEmitter} from '@angular/core';\nimport {GadgetInstanceService} from './grid.service';\nimport {ConfigurationService} from '../services/configuration.service';\nimport {GadgetConfigModel} from '../gadgets/_common/gadget-config-model';\nimport {AddGadgetService} from '../add-gadget/service';\nimport {ToastService} from '../toast/toast.service';\nimport {MenuEventService} from '../menu/menu-service';\n\n\n@Component({\n    moduleId: module.id,\n    selector: 'app-grid-component',\n    templateUrl: './grid.html',\n    styleUrls: ['./styles-grid.css']\n})\nexport class GridComponent {\n    @Output() boardUpdateEvent: EventEmitter<any> = new EventEmitter();\n\n    model: any = {};\n    noGadgets = true;\n    dashedStyle: {};\n    dropZone1: any = null;\n    dropZone2: any = null;\n    dropZone3: any = null;\n\n    gadgetLibrary: any[] = [];\n\n    /** todo\n     * Temporary objects for experimenting with AI\n     * @type\n     */\n\n    gridInsertionPosition = {\n        x: 0,\n        y: 0\n    };\n\n    /**\n     * Todo - split model and board operations. This class should really focus on an individual board model's operations\n     * within the grid. The board specific operations should be moved to the board component.\n     * @param _gadgetInstanceService\n     * @param _procmonConfigurationService\n     */\n\n    constructor(private _gadgetInstanceService: GadgetInstanceService,\n                private _configurationService: ConfigurationService,\n                private _gadgetLibraryService: AddGadgetService,\n                private _toastService: ToastService,\n                private _menuEventService: MenuEventService) {\n\n\n        this.removeOldListeners();\n\n        this.setupEventListeners();\n        this.initializeBoard();\n        this.getGadgetLibrary();\n\n    }\n\n    /**\n     * todo - This is a temporary attempt to avoid emitting events from stale listeners.\n     * Most severe symptom is when you drill down and then change the layout.\n     * Multiple events are triggered per action due to the services not\n     * getting destroyed when coming into the main board from a child route. The end result is multiple gadget instances\n     * appearing. The following code improves the condition but there still are issues with multiple gadgets appearing\n     * when changing the layout.\n     *\n     */\n    removeOldListeners(){\n\n        this._gadgetInstanceService.unSubscribeAll();\n        this._menuEventService.unSubscribeAll();\n\n    }\n\n    setupEventListeners() {\n\n        let gadgetRemoveEventSubscriber = this._gadgetInstanceService.listenForInstanceRemovedEventsFromGadgets().subscribe((message: string) => {\n            this.saveBoard('Gadget Removed From Board: ' + message, false);\n        });\n\n\n        let menuEventSubscriber = this._menuEventService.listenForMenuEvents().subscribe((event: IEvent) => {\n            const edata = event['data'];\n\n            switch (event['name']) {\n                case 'boardChangeLayoutEvent':\n                    this.updateBoardLayout(edata);\n                    break;\n                case 'boardSelectEvent':\n                    this.loadBoard(edata);\n                    break;\n                case 'boardCreateEvent':\n                    this.createBoard(edata);\n                    break;\n                case 'boardEditEvent':\n                    this.editBoard(edata);\n                    break;\n                case 'boardDeleteEvent':\n                    this.deleteBoard(edata);\n                    break;\n                case 'boardAddGadgetEvent':\n                    this.addGadget(edata);\n                    break;\n                case 'boardAIAddGadgetEvent':\n                    this.addGadgetUsingArtificialIntelligence(edata);\n                    break;\n            }\n        });\n\n        this._gadgetInstanceService.addSubscriber(gadgetRemoveEventSubscriber);\n        this._menuEventService.addSubscriber(menuEventSubscriber);\n\n    }\n\n    /**\n     *\n     * This is experimental code that deals with AI\n     */\n    getGadgetLibrary() {\n\n        this._gadgetLibraryService.getGadgetLibrary().subscribe(data => {\n            this.gadgetLibrary.length = 0;\n            const me = this;\n            data.library.forEach(function (item) {\n                me.gadgetLibrary.push(item);\n            });\n        });\n    }\n\n    getGadgetFromLibrary(gadgetType: string) {\n\n        let gadgetObject = null;\n        this.gadgetLibrary.forEach(gadget => {\n\n\n            if (gadgetType.localeCompare(gadget['componentType']) === 0) {\n\n                gadgetObject = gadget;\n            }\n        });\n        return gadgetObject;\n    }\n\n    addGadgetUsingArtificialIntelligence(aiObject: any) {\n\n        /** todo\n         * make confidence code configurable\n         */\n        if (aiObject && aiObject.operation) {\n            switch (aiObject.operation) {\n                case 'get_storage':\n                    this.addGadget(this.getGadgetFromLibrary('StorageObjectListComponent'));\n                    break;\n                case 'get_cpu':\n                    this.addGadget(this.getGadgetFromLibrary('CPUGadgetComponent'));\n                    break;\n            }\n        }\n    }\n\n    /**\n     * This is the end of the experimental AI code.\n     */\n\n    updateGadgetPositionInBoard($event, columnNumber, rowNumber, type) {\n        let moveComplete = false;\n\n        this.getModel().rows.forEach(row => {\n\n            let colpos = 0;\n\n            row.columns.forEach(column => {\n\n                let gadgetpos = 0;\n\n                if (column.gadgets) {\n\n                    column.gadgets.forEach(_gadget => {\n\n                        if (_gadget.instanceId === $event.dragData && !moveComplete) {\n\n                            const gadget = column.gadgets.splice(gadgetpos, 1);\n\n\n                            if (!this.getModel().rows[rowNumber].columns[columnNumber].gadgets) {\n                                this.getModel().rows[rowNumber].columns[columnNumber].gadgets = [];\n                            }\n                            this.getModel().rows[rowNumber].columns[columnNumber].gadgets.push(gadget[0]);\n                            this.saveBoard('drag drop operation', false);\n                            moveComplete = true;\n                        }\n                        gadgetpos++;\n                    });\n                    colpos++;\n                }\n            });\n        });\n    }\n\n    public createBoard(name: string) {\n        this.loadNewBoard(name);\n    }\n\n    public editBoard(name: string) {\n\n    }\n\n    public deleteBoard(name: string) {\n\n        this._configurationService.deleteBoard(name).subscribe(data => {\n\n                this.initializeBoard();\n\n            },\n            error => console.error('Deletion error', error),\n            () => console.debug('Board Deletion: ' + name));\n\n    }\n\n    public addGadget(gadget: any) {\n\n        //console.log(\"Adding Gadget!!!!!!!@#@##@#@#@#@#@#@@\");\n\n        const _gadget = Object.assign({}, gadget);\n\n        _gadget.instanceId = new Date().getTime();\n        _gadget.config = new GadgetConfigModel(gadget.config);\n\n        this.setGadgetInsertPosition();\n\n        const x = this.gridInsertionPosition.x;\n        const y = this.gridInsertionPosition.y;\n\n        if (!this.getModel().rows[x].columns[y].gadgets) {\n\n            this.getModel().rows[x].columns[y].gadgets = [];\n        }\n        this.getModel().rows[x].columns[y].gadgets.push(_gadget);\n\n        this.saveBoard('Adding Gadget To The Board', false);\n\n    }\n\n    public updateBoardLayout(structure) {\n\n        console.log(\"IN UPDATE BOARD LAYOUT\");\n\n        // user selected the currently selected layout\n        if (structure.id === this.getModel().id) {\n            return;\n        }\n\n        // copy the current board's model\n        const _model = Object.assign({}, this.getModel());\n\n        // get just the columns that contain gadgets from all rows\n        const originalColumns: any[] = this.readColumnsFromOriginalModel(_model);\n\n        // reset the copied model's rows, which include columns\n        _model.rows.length = 0;\n\n        // copy the contents of the requested structure into the temporary model\n        // we now have a board model we can populate with the original board's gadgets\n        Object.assign(_model.rows, structure.rows);\n        _model.structure = structure.structure;\n        _model.id = structure.id;\n\n        let originalColumnIndexToStartProcessingFrom = 0;\n\n        /* For each column from the original board, copy its gadgets to the new structure.\n         The requested layout may have more or less columns than defined by the original layout. So the fillGridStructure method\n         will copy column content into the target. If there are more columns than the target,\n         the fillGridStructure will return the count of remaining columns to be processed and then process those.\n         */\n        while (originalColumnIndexToStartProcessingFrom < originalColumns.length) {\n            originalColumnIndexToStartProcessingFrom = this.fillGridStructure(_model, originalColumns, originalColumnIndexToStartProcessingFrom);\n        }\n\n        // This will copy the just processed model and present it to the board\n        this.setModel(_model);\n\n        // clear temporary object\n        for (const member in  _model) {\n            delete  _model[member];\n        }\n\n        // persist the board change\n        this.saveBoard('Grid Layout Update', false);\n    }\n\n    private updateGridState() {\n\n        let gadgetCount = 0;\n\n        if (this.getModel().rows) {\n            this.getModel().rows.forEach(function (row) {\n                row.columns.forEach(function (column) {\n                    if (column.gadgets) {\n                        column.gadgets.forEach(function (gadget) {\n                            gadgetCount++;\n                        });\n                    }\n                });\n            });\n        }\n\n        this.noGadgets = !gadgetCount;\n\n        this.dashedStyle = {\n            'border-style': this.noGadgets ? 'dashed' : 'none',\n            'border-width': this.noGadgets ? '2px' : 'none',\n            'border-color': this.noGadgets ? 'darkgray' : 'none',\n            'padding': this.noGadgets ? '5px' : 'none'\n        };\n    }\n\n    private readColumnsFromOriginalModel(_model) {\n\n        const columns = [];\n        _model.rows.forEach(function (row) {\n            row.columns.forEach(function (col) {\n                columns.push(col);\n            });\n        });\n        return columns;\n\n    }\n\n    private fillGridStructure(destinationModelStructure, originalColumns: any[], counter: number) {\n\n        const me = this;\n\n        destinationModelStructure.rows.forEach(function (row) {\n            row.columns.forEach(function (destinationColumn) {\n                if (!destinationColumn.gadgets) {\n                    destinationColumn.gadgets = [];\n                }\n                if (originalColumns[counter]) {\n                    me.copyGadgets(originalColumns[counter], destinationColumn);\n                    counter++;\n                }\n            });\n        });\n\n        return counter;\n\n    }\n\n    private copyGadgets(source, target) {\n\n        if (source.gadgets && source.gadgets.length > 0) {\n            let w = source.gadgets.shift();\n            while (w) {\n                target.gadgets.push(w);\n                w = source.gadgets.shift();\n            }\n        }\n    }\n\n    public enableConfigMode() {\n\n        this._gadgetInstanceService.enableConfigureMode();\n    }\n\n    private initializeBoard() {\n\n        this._configurationService.getBoards().subscribe(board => {\n\n            if (board && board instanceof Array && board.length) {\n\n                const sortedBoard = board.sort(function (a, b) {\n                    return a.boardInstanceId - b.boardInstanceId;\n                });\n\n                this.loadBoard(sortedBoard[0].title);\n            } else {\n\n                this.loadDefaultBoard();\n            }\n        });\n    }\n\n    private loadBoard(boardTitle: string) {\n\n        this.clearGridModelAndGadgetInstanceStructures();\n\n        this._configurationService.getBoardByTitle(boardTitle).subscribe(board => {\n\n                this.setModel(board);\n                this.updateServicesAndGridWithModel();\n                this.boardUpdateEvent.emit(boardTitle);\n            },\n            error => {\n                console.error(error);\n                this.loadDefaultBoard();\n\n            });\n\n    }\n\n    private loadDefaultBoard() {\n\n        this.clearGridModelAndGadgetInstanceStructures();\n\n        this._configurationService.getDefaultBoard().subscribe(board => {\n\n            this.setModel(board);\n            this.updateServicesAndGridWithModel();\n            this.saveBoard('Initialization of a default board', true);\n\n\n        });\n    }\n\n    private loadNewBoard(name: string) {\n\n        this.clearGridModelAndGadgetInstanceStructures();\n\n        this._configurationService.getDefaultBoard().subscribe(res => {\n\n            this.setModel(res);\n            this.getModel().title = name;\n            this.getModel().boardInstanceId = new Date().getTime();\n\n            this.updateServicesAndGridWithModel();\n            this.saveBoard('Initialization of a new board', true);\n\n\n        });\n    }\n\n    private updateServicesAndGridWithModel() {\n        this._gadgetInstanceService.setCurrentModel(this.getModel());\n        this._configurationService.setCurrentModel(this.getModel());\n        this.updateGridState();\n    }\n\n    private saveBoard(operation: string, alertBoardListenerThatTheMenuShouldBeUpdated: boolean) {\n\n        this.updateServicesAndGridWithModel();\n\n        this._configurationService.saveBoard(this.getModel()).subscribe(result => {\n\n                this._toastService.sendMessage(this.getModel().title + ' has been updated!', '');\n\n                if (alertBoardListenerThatTheMenuShouldBeUpdated) {\n                    this._menuEventService.raiseGridEvent({name: 'boardUpdateEvent', data: this.getModel().title});\n                }\n            },\n            error => console.error('Error' + error),\n            () => console.debug('Saving configuration to store!'));\n\n    }\n\n    private clearGridModelAndGadgetInstanceStructures() {\n// clear gadgetInstances\n        this._gadgetInstanceService.clearAllInstances();\n// clear current model\n        for (const prop in this.getModel()) {\n            if (this.model.hasOwnProperty(prop)) {\n                delete this.model[prop];\n            }\n        }\n    }\n\n    private setGadgetInsertPosition() {\n\n        for (let x = 0; x < this.getModel().rows.length; x++) {\n\n            for (let y = 0; y < this.getModel().rows[x].columns.length; y++) {\n\n                if (this.getModel().rows[x].columns[y].gadgets && this.getModel().rows[x].columns[y].gadgets.length === 0) {\n\n                    this.gridInsertionPosition.x = x;\n                    this.gridInsertionPosition.y = y;\n                    return;\n\n                }\n            }\n        }\n// we go here because the board is either empty or full\n// insert in the top left most cell\n        this.gridInsertionPosition.y = 0;\n\n        if (this.noGadgets) {\n            // there are no gadgets so insert in top row\n            this.gridInsertionPosition.x = 0;\n        } else {\n            // board is full so insert in the last row\n            this.gridInsertionPosition.x = this.getModel().rows.length - 1;\n        }\n    }\n\n    public setModel(model: any) {\n\n        this.model = Object.assign({}, model);\n    }\n\n    public getModel() {\n        return this.model;\n    }\n\n\n}\n"
  },
  {
    "path": "src/app/grid/grid.html",
    "content": "<div class=\"ui centered stackable grid\" style=\"margin-left: 5px; margin-right: 5px\">\n    <div *ngFor=\"let row of model.rows; let r = index\" class=\"row\"\n         [ngClass]=\"{'short-row': row.columns.length > 3, 'tall-row': row.columns.length <= 3 }\">\n\n        <div *ngFor=\"let col of row.columns; let c = index\" class=\"{{col.styleClass}} column\" dnd-droppable\n             [dropZones]=\"['c' + c]\" (onDropSuccess)=\"updateGadgetPositionInBoard($event, c, r, 'column')\">\n\n            <div *ngIf=\"!col.gadgets || col.gadgets.length== 0\" class=\"ui center aligned massive info message\"\n                 style=\"text-align:center\"\n                 [ngClass]=\"{'short-row': row.columns.length > 3, 'tall-row': row.columns.length <= 3 }\">\n\n                <span style=\"font-size: .75em\">Add Gadget!</span>\n\n            </div>\n\n            <app-grid-cell *ngFor=\"let cellGadget of col.gadgets\"\n\n                           [gadgetInstanceId]=\"cellGadget.instanceId\"\n                           [gadgetConfig]=\"cellGadget.config\"\n                           [gadgetType]=\"cellGadget.componentType\"\n                           [gadgetTags]=\"cellGadget.tags\"\n\n            >\n\n            </app-grid-cell>\n\n        </div>\n\n    </div>\n\n</div>\n\n<app-toast></app-toast>"
  },
  {
    "path": "src/app/grid/grid.module.ts",
    "content": "import {NgModule, ANALYZE_FOR_ENTRY_COMPONENTS} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {FormsModule} from '@angular/forms';\n\nimport {GridComponent} from './grid.component';\nimport {CellComponent} from './cell.component';\nimport {GadgetInstanceService} from './grid.service';\nimport {ConfigurationService} from '../services/configuration.service';\nimport {AddGadgetService} from '../add-gadget/service';\nimport {DndModule} from 'ng2-dnd';\nimport {NewsService} from '../gadgets/news/service';\nimport {JobAnalysisService} from '../gadgets/job-analysis/service';\nimport {TrendService} from '../gadgets/trend/service';\nimport {TrendLineService} from '../gadgets/trend-line/service';\nimport {EdgeService} from '../gadgets/edge-service-list/service';\nimport {CPUService} from '../gadgets/cpu/service';\nimport {HttpClientModule} from '@angular/common/http';\nimport {DonutService} from '../gadgets/donut/service';\nimport {TodoService} from '../gadgets/todo/service';\nimport {ToastModule} from '../toast/toast.module';\nimport {ConnectionService} from '../gadgets/port-connection/service';\nimport {BubbleService} from \"../gadgets/bubble/service\";\nimport {BarChartService} from \"../gadgets/barchart/service\";\nimport {PieChartService} from \"../gadgets/piechart/service\";\n\n\n@NgModule({\n    imports: [\n        CommonModule,\n        FormsModule,\n        ToastModule,\n        HttpClientModule, DndModule.forRoot()\n    ],\n    declarations: [\n        GridComponent,\n        CellComponent\n    ],\n    exports: [\n        GridComponent\n    ],\n    providers: [\n        GadgetInstanceService,\n        ConfigurationService,\n        AddGadgetService,\n        NewsService,\n        JobAnalysisService,\n        TrendLineService,\n        TrendService,\n        EdgeService,\n        CPUService,\n        DonutService,\n        ConnectionService,\n        TodoService  // todo gadget\n        ,BubbleService,\n        BarChartService,\n        PieChartService\n    ]\n})\nexport class GridModule {\n    static withComponents(components: any[]) {\n        return {\n            ngModule: GridModule,\n            providers: [\n                {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: components, multi: true}\n            ]\n        };\n    }\n}\n"
  },
  {
    "path": "src/app/grid/grid.service.ts",
    "content": "/**\n * Created by jayhamilton on 1/28/17.\n */\nimport {Injectable} from '@angular/core';\nimport {Subject,Observable} from 'rxjs';\n\n/**\n * todo - the name of this service does not represent the file name. This should be refactored. Consider moving this service to the gadget module instead.\n */\n\n@Injectable()\nexport class GadgetInstanceService {\n\n    private concreteGadgetInstances: any[] = [];\n    private model: any;\n    private subject: Subject<string> = new Subject<string>();\n    private subscribers: Array<Subject<string>> = [];\n\n    constructor() {\n    }\n\n    addInstance(gadget: any) {\n        let gadgetFound = false;\n\n        for (let x = 0; x < this.concreteGadgetInstances.length; x++) {\n            if (gadget.instance.instanceId == this.concreteGadgetInstances[x]['instance']['instanceId']) {\n                gadgetFound = true;\n            }\n        }\n\n        if (gadgetFound == false) {\n            this.concreteGadgetInstances.push(gadget);\n\n        }\n    }\n\n    enableConfigureMode() {\n\n        this.concreteGadgetInstances.forEach(function (gadget) {\n            gadget.instance.toggleConfigMode();\n        });\n    }\n\n    removeInstance(id: number) {\n\n        console.log(\"REMOVING GADGET\");\n        // remove instance representation from model\n        this.model.rows.forEach(function (row) {\n            row.columns.forEach(function (column) {\n                if (column.gadgets) {\n                    for (let i = column.gadgets.length - 1; i >= 0; i--) {\n\n                        if (column.gadgets[i].instanceId === id) {\n\n                            column.gadgets.splice(i, 1);\n\n                            break;\n                        }\n                    }\n                }\n            });\n        });\n\n        // removes concrete instance from service\n        for (let x = this.concreteGadgetInstances.length - 1; x >= 0; x--) {\n\n            if (this.concreteGadgetInstances[x].instance.instanceId === id) {\n\n                const _gadget = this.concreteGadgetInstances.splice(x, 1);\n\n                _gadget[0].destroy();\n\n                break;\n            }\n        }\n\n        // raise an event indicating a gadget was removed\n        this.subject.next('gadget id: ' + id);\n    }\n\n    getInstanceCount() {\n        return this.concreteGadgetInstances.length;\n    }\n\n    /*\n     this allows this service to update the board when a delete operation occurs\n     */\n    setCurrentModel(model: any) {\n\n        this.model = model;\n    }\n\n    /*\n     raise an event that the grid.component is listening for when a gadget is removed.\n     */\n    listenForInstanceRemovedEventsFromGadgets(): Observable<string> {\n        return this.subject.asObservable();\n    }\n\n    addSubscriber(subscriber: any) {\n        this.subscribers.push(subscriber);\n    }\n\n    unSubscribeAll() {\n\n        this.subscribers.forEach(subscription => {\n            subscription.unsubscribe();\n        });\n\n        this.subscribers.length = 0;\n        this.clearAllInstances();\n\n    }\n    clearAllInstances() {\n\n        this.concreteGadgetInstances.length = 0;\n    }\n\n}\n"
  },
  {
    "path": "src/app/grid/styles-grid.css",
    "content": ".ui.info.message {\n    background-color: #C8CBCE;\n    color: #ffffff\n}\n\n.ui.attached.info.message, .ui.info.message {\n    box-shadow: 0 0 0 0 px #c8cbce inset, 0 0 0 0 transparent;\n}\n\n.short-row{\n    min-height:150px;\n}\n\n.tall-row{\n    min-height:370px;\n}\n\n"
  },
  {
    "path": "src/app/layout/layout-component.ts",
    "content": "/**\n * Created by jayhamilton on 1/24/17.\n */\nimport {\n    AfterViewInit, Component, Output, EventEmitter, Input\n} from '@angular/core';\n\nimport {boardLayouts} from './model';\n\n\n/**\n * Message Modal - clasable modal with message\n *\n * Selector message-modal\n *\n * Methods\n *      popMessageModal - display a message modal for a sepcified duration\n *      showMessageModal - show the message modal\n *      hideMessageModal - hide the message modal\n */\n@Component({\n    selector: 'app-board-layout-manager-modal',\n    moduleId: module.id,\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css']\n\n})\nexport class BoardLayoutManagerComponent implements AfterViewInit {\n\n    @Input() layoutId;\n    @Output() boardLayoutChangeEvent: EventEmitter<any> = new EventEmitter();\n\n    boardLayouts: any[];\n\n    modalHeader = 'Layout';\n\n    messageModal: any;\n\n    constructor() {\n        this.initializeLayouts();\n    }\n\n    selectBoardLayout(layoutId: number) {\n\n        for (let x = 0; x < this.boardLayouts.length; x++) {\n\n            if (this.boardLayouts[x].id === layoutId) {\n                this.boardLayoutChangeEvent.emit(this.boardLayouts[x]);\n                this.layoutId = layoutId;\n                break;\n            }\n        }\n    }\n\n    ngAfterViewInit() {\n\n    }\n\n    initializeLayouts() {\n\n        Object.assign(this, {boardLayouts});\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/layout/layout.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {BoardLayoutManagerComponent} from './layout-component';\n\n@NgModule({\n    imports: [\n        CommonModule\n    ],\n    declarations: [BoardLayoutManagerComponent],\n    exports: [BoardLayoutManagerComponent]\n})\nexport class LayoutModule {\n}\n"
  },
  {
    "path": "src/app/layout/model.ts",
    "content": "/**\n * Created by jayhamilton on 1/31/17.\n */\nexport const boardLayouts = [\n\n    {\n        id: 0,\n        boardInstanceId: 0,\n        title: 'one-narrow',\n        checked: false,\n        structure: '8',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'eight wide',\n\n                }]\n        }]\n    },\n    {\n        id: 1,\n        boardInstanceId: 1,\n        title: 'single',\n        checked: false,\n        structure: '14',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'fourteen wide',\n\n                }]\n        }]\n    },\n    {\n        id: 2,\n        boardId: 2,\n        title: 'narrow-right',\n        checked: false,\n        structure: '10-6',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'ten wide',\n\n                },\n                {\n                    styleClass: 'six wide',\n\n                }]\n        }]\n    },\n    {\n        id: 3,\n        boardInstanceId: 3,\n        title: 'wide-center',\n        checked: false,\n        structure: '4-8-4',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'four wide',\n\n                },\n                {\n                    styleClass: 'eight wide',\n\n                },\n                {\n                    styleClass: 'four wide',\n\n                }]\n        }]\n    },\n    {\n        id: 4,\n        boardInstanceId: 4,\n        title: 'narrow-left',\n        checked: false,\n        structure: '4-12',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'four wide',\n\n                },\n                {\n                    styleClass: 'twelve wide',\n\n                }]\n        }]\n    },\n    {\n        id: 5,\n        boardInstanceId: 5,\n        title: 'two-even',\n        checked: true,\n        structure: '6-6',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'six wide',\n\n                },\n                {\n                    styleClass: 'six wide',\n\n                }]\n        }]\n    },\n    {\n        id: 6,\n        boardInstanceId: 6,\n        title: 'three-even',\n        checked: false,\n        structure: '5-5-5',\n        rows: [{\n            columns: [\n                {\n                    styleClass: 'four wide',\n\n                },\n                {\n                    styleClass: 'four wide',\n\n                },\n                {\n                    styleClass: 'four wide',\n\n                }\n            ]\n        }]\n    },\n    {\n        id: 7,\n        boardInstanceId: 7,\n        title: 'wide-top',\n        checked: false,\n        structure: '16/8-8',\n        rows: [\n            {\n                columns: [\n                    {\n                        styleClass: 'twelve wide'\n                    }\n                ]\n            },\n            {\n                columns: [\n                    {\n                        styleClass: 'six wide'\n                    },\n                    {\n                        styleClass: 'six wide'\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        id: 8,\n        boardInstanceId: 8,\n        title: 'ngadmin',\n        checked: false,\n        structure: '4-4-4-4/8-4-4',\n        rows: [\n            {\n                columns: [\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    }\n                ]\n            },\n            {\n                columns: [\n                    {\n                        styleClass: 'eight wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    },\n                    {\n                        styleClass: 'four wide'\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        id: 9,\n        boardInstanceId: 9,\n        title: 'google-layout',\n        checked: false,\n        structure: '3-6-3',\n        rows: [\n            {\n                columns: [\n                    {\n                        styleClass: 'three wide'\n                    },\n                    {\n                        styleClass: 'six wide'\n                    },\n                    {\n                        styleClass: 'three wide'\n                    }\n                ]\n            }\n        ]\n    }\n\n];\n"
  },
  {
    "path": "src/app/layout/styles.css",
    "content": "\n.layout-selected {\n    border-top: medium lawngreen solid;\n    padding-top:5px;\n}\nul{\n    text-align: center;\n}\nh2{\n    color:white !important;\n}\nul, menu, dir {\n    -webkit-padding-start: 5px;\n}"
  },
  {
    "path": "src/app/layout/view.html",
    "content": "<br>\n\n<div style=\"text-align: center\">\n    <h2>{{modalHeader}}</h2>\n</div>\n<hr>\n\n<br>\n<br>\n<ul>\n    <li style='list-style: none'\n        *ngFor=\"let layout of boardLayouts; let i = index\">\n        <img [ngClass]=\"{'layout-selected': layoutId == layout.id }\" src=\"/assets/images/{{layout.title}}.png\"\n             (click)=\"selectBoardLayout(layout.id)\">\n\n    </li>\n</ul>\n\n\n\n"
  },
  {
    "path": "src/app/menu/IEvent.ts",
    "content": "interface IEvent {\n    name: string;\n    data: any;\n}\n"
  },
  {
    "path": "src/app/menu/menu-service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {Subject, Observable} from 'rxjs';\n\n/**\n The grid is primarily controlled by MenuService Events. You can change the behavior by\n changing the MenuComponent and have it call methods within the Grid component via Output Events\n within the Menu component or by using the @ViewChild approach.\n\n In the current code, the MenuService is shared by the GridComponent and MenuComponent.\n The MenuComponent relays events from the various components that make up the MenuComponent.\n The GridComponent listens for those events via an Observable. The GridComponent will also\n raise/emit an event that will be picked up by the MenuComponent via the MenuService through an Observable as well.\n */\n\n@Injectable()\nexport class MenuEventService {\n\n    private menuSubject: Subject<IEvent> = new Subject<IEvent>();\n    private gridSubject: Subject<IEvent> = new Subject<IEvent>();\n    private subscribers: Array<Subject<string>> =[];\n\n    constructor() {\n    }\n\n    raiseMenuEvent(event: IEvent) {\n        this.menuSubject.next(event);\n    }\n\n    listenForMenuEvents(): Observable<IEvent> {\n        return this.menuSubject.asObservable();\n    }\n\n\n    raiseGridEvent(event: IEvent) {\n        this.menuSubject.next(event);\n    }\n\n    listenForGridEvents(): Observable<IEvent> {\n        return this.gridSubject.asObservable();\n    }\n\n    addSubscriber(subscriber:any){\n        this.subscribers.push(subscriber);\n    }\n    unSubscribeAll(){\n\n        this.subscribers.forEach(subscription=>{\n            subscription.unsubscribe();\n        });\n\n        this.subscribers.length = 0;\n\n    }\n}\n"
  },
  {
    "path": "src/app/menu/menu.component.ts",
    "content": "import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';\nimport {ConfigurationService} from '../services/configuration.service';\nimport {MenuEventService} from './menu-service';\nimport {environment} from '../../environments/environment';\n\n\ndeclare var jQuery: any;\n\n\n/**a\n * Menu component\n *\n */\n@Component({\n    moduleId: module.id,\n    selector: 'app-menu-component',\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css'],\n\n})\nexport class MenuComponent implements OnInit {\n\n    host = window.location.host;\n    dashboardList: any[] = [];\n    selectedBoard = '';\n    placeHolderText = 'Ask the board to do something!';\n    searchList: Array<string> = [];\n    env: any;\n\n    @ViewChild('notificationSideBar_tag') notificationSideBarRef: ElementRef;\n    @ViewChild('layoutSideBar_tag') layoutSideBarRef: ElementRef;\n    @ViewChild('aboutSideBar_tag') aboutSideBarRef: ElementRef;\n    @ViewChild('stickymenu_tag') stickyMenuRef: ElementRef;\n\n    notificationSideBar: any;\n    layoutSideBar: any;\n    aboutSideBar:any;\n    stickyMenu: any;\n\n    typeAheadIsInMenu = true;\n\n    layoutId = 0;\n\n    constructor(private _configurationService: ConfigurationService,\n                private _menuEventService: MenuEventService) {\n\n        this._menuEventService.unSubscribeAll();\n\n        this.setupEventListeners();\n        this.env = environment;\n    }\n\n    setupEventListeners() {\n       let gridEventSubscription =  this._menuEventService.listenForGridEvents().subscribe((event: IEvent) => {\n\n            const edata = event['data'];\n\n            switch (event['name']) {\n                case 'boardUpdateEvent':\n                    this.updateDashboardMenu(edata);\n                    break;\n            }\n\n        });\n\n       this._menuEventService.addSubscriber(gridEventSubscription);\n\n    }\n\n    ngOnInit() {\n        this.updateDashboardMenu('');\n        this.stickyMenu = jQuery(this.stickyMenuRef.nativeElement);\n        this.stickyMenu.sticky();\n    }\n\n    emitBoardChangeLayoutEvent(event) {\n        this._menuEventService.raiseMenuEvent({name: 'boardChangeLayoutEvent', data: event});\n    }\n\n    emitBoardSelectEvent(event) {\n        this.boardSelect(event);\n        this._menuEventService.raiseMenuEvent({name: 'boardSelectEvent', data: event});\n    }\n\n    emitBoardCreateEvent(event) {\n        this._menuEventService.raiseMenuEvent({name: 'boardCreateEvent', data: event});\n        this.updateDashboardMenu(event);\n    }\n\n    emitBoardEditEvent(event) {\n        this._menuEventService.raiseMenuEvent({name: 'boardEditEvent', data: event});\n    }\n\n    emitBoardDeleteEvent(event) {\n        this._menuEventService.raiseMenuEvent({name: 'boardDeleteEvent', data: event});\n        this.updateDashboardMenu('');\n    }\n\n    emitBoardAddGadgetEvent(event) {\n        this._menuEventService.raiseMenuEvent({name: 'boardAddGadgetEvent', data: event});\n    }\n\n    emitBoardAIAddGadgetEvent(event) {\n        this._menuEventService.raiseMenuEvent({name: 'boardAIAddGadgetEvent', data: event});\n    }\n\n    updateDashboardMenu(selectedBoard: string) {\n\n        this._configurationService.getBoards().subscribe(data => {\n\n            const me = this;\n            if (data && data instanceof Array && data.length) {\n                this.dashboardList.length = 0;\n\n\n                // sort boards\n                data.sort((a: any, b: any) => a.boardInstanceId - b.boardInstanceId);\n\n                data.forEach(board => {\n\n                    me.dashboardList.push(board.title);\n\n                });\n\n                if (selectedBoard === '') {\n\n                    this.boardSelect(this.dashboardList[0]);\n\n                } else {\n\n                    this.boardSelect(selectedBoard);\n                }\n            }\n        });\n    }\n\n    boardSelect(selectedBoard: string) {\n        this.selectedBoard = selectedBoard;\n    }\n\n    toggleLayoutSideBar() {\n        this.layoutSideBar = jQuery(this.layoutSideBarRef.nativeElement);\n        this.layoutSideBar.sidebar('setting', 'transition', 'overlay');\n        this.layoutSideBar.sidebar('toggle');\n        this.layoutId = this._configurationService.currentModel.id;\n    }\n\n    toggleNotificationSideBar() {\n        this.notificationSideBar = jQuery(this.notificationSideBarRef.nativeElement);\n        this.notificationSideBar.sidebar('setting', 'transition', 'overlay');\n        this.notificationSideBar.sidebar('toggle');\n    }\n    toggleAboutSideBar() {\n        this.aboutSideBar = jQuery(this.aboutSideBarRef.nativeElement);\n        this.aboutSideBar.sidebar('setting', 'transition', 'overlay');\n        this.aboutSideBar.sidebar('toggle');\n    }\n\n\n    public showDocumentation() {\n\n        window.location.href = 'http://' + window.location.host + '/assets/documentation/index.html';\n    }\n\n}\n"
  },
  {
    "path": "src/app/menu/menu.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {MatButtonModule, MatIconModule} from '@angular/material';\nimport {DndModule} from 'ng2-dnd';\nimport {GadgetModule} from '../gadgets/gadget.module';\nimport {ConfigurationModule} from '../configuration/configuration.module';\nimport {LayoutModule} from '../layout/layout.module';\nimport {AddGadgetModule} from '../add-gadget/add-gadget.module';\nimport {NotificationModule} from '../notification/notification.module';\nimport {GadgetPropertyService} from '../gadgets/_common/gadget-property.service';\nimport {ConfigurationService} from '../services/configuration.service';\nimport {RuntimeService} from '../services/runtime.service';\nimport {EndPointService} from '../configuration/tab-endpoint/endpoint.service';\nimport {ObservableWebSocketService} from '../services/websocket-service';\nimport {TypeAheadInputModule} from '../typeahead-input/typeahead-input.module';\nimport {MenuComponent} from './menu.component';\nimport {MenuEventService} from './menu-service';\nimport {AboutModule} from \"../about/about.module\";\n\n@NgModule({\n    imports: [\n        CommonModule,\n        NotificationModule,\n        AddGadgetModule,\n        LayoutModule,\n        AboutModule,\n        ConfigurationModule,\n        TypeAheadInputModule,\n        GadgetModule,\n        DndModule.forRoot(),\n        MatButtonModule, MatIconModule,\n    ],\n    providers: [EndPointService,\n        RuntimeService,\n        ConfigurationService,\n        GadgetPropertyService,\n        ObservableWebSocketService,\n        MenuEventService\n    ],\n    declarations: [\n        MenuComponent\n    ],\n    exports: [\n        MenuComponent\n    ]\n})\nexport class MenuModule {\n}\n"
  },
  {
    "path": "src/app/menu/styles.css",
    "content": "\n\n.ui.secondary.pointing.menu .active.item {\n    color: #f9f9f9 !important;\n    font-weight: 500 !important;\n    border-color: #00ff00 !important;\n    border-width: medium !important;\n    font-family: 'Roboto', sans-serif !important;\n    font-size: 1.2em;\n}\n\n.ui.secondary.pointing.menu .item {\n    color: rgba(128, 128, 128, 0.7) !important;\n    font-weight: 500 !important;\n    font-family: 'Roboto', sans-serif !important;\n    font-size: 1.2em;\n}\n\n.ui.secondary.pointing.menu {\n    border-bottom: none !important;\n}\n\n\ninput {\n    padding: 5px;\n    font-weight: 300 !important;\n    font-family: 'Roboto', sans-serif !important;\n    font-size: 1.1em;\n    outline: none !important;\n}\n\n.ui.floating.label{\n    top:.5em;\n    margin:0;\n}\n.ui.menu .item>.floating.label{\n    padding:.3em .6em\n}\n\n.ui.menu{\n    border-radius:0px;\n}\n.ui.inverted.menu{\n    background-color: #1C2B36;\n}\n\n.ui.menu .item>i.icon {\n    margin: 0;\n}\n\n"
  },
  {
    "path": "src/app/menu/view.html",
    "content": "<div  class=\"ui inverted menu sticky\" #stickymenu_tag style=\"height: 66px !important\">\n\n\n    <app-typeahead-input *ngIf=\"env.menu.aiSearch\"  style=\"width:25%; padding-bottom:0\" class=\"item\"\n                         [searchList]=\"searchList\"\n                         [placeHolderText]=\"placeHolderText\"\n                         [typeAheadIsInMenu]=\"typeAheadIsInMenu\"\n                         (ArtificialIntelligenceEventEmitter)=\"emitBoardAIAddGadgetEvent($event)\">\n    </app-typeahead-input>\n\n\n    <div class=\"ui secondary inverted pointing menu board\">\n        <a *ngFor=\"let board of dashboardList; let i = index\" class=\"item\"\n           [ngClass]=\"{'active':board == selectedBoard}\"\n           (click)=\"emitBoardSelectEvent(board)\">\n            {{board}}\n        </a>\n    </div>\n\n\n    <div class=\"right inverted menu\">\n\n\n        <a  *ngIf=\"env.menu.documentation\"  class=\"item\"\n          (click)=\"showDocumentation()\">\n            <i class=\"large inverted book icon\"></i>\n        </a>\n\n        <a *ngIf=\"env.menu.notification\"  class=\"item\"\n           (click)=\"toggleNotificationSideBar()\">\n            <i class=\"large inverted alarm icon\"></i>\n            <div class=\"floating ui red label\">\n                <span style=\"font-size: 1.2em; font-weight: normal\">4</span>\n            </div>\n        </a>\n\n\n        <a class=\"item\"\n           (click)=\"addGadgetModal.showComponentLibraryModal('Add Gadget')\">\n            <i class=\"large inverted plus icon\"></i>\n        </a>\n\n\n        <a class=\"item\"\n           (click)=\"toggleLayoutSideBar()\">\n            <i class=\"large inverted grid layout icon\"></i>\n        </a>\n\n\n        <a class=\"item\"\n           (click)=\"boardConfigModal.showConfigurationModal('Configuration')\">\n            <i class=\"large inverted setting icon\"></i>\n        </a>\n\n\n        <a class=\"item\"\n           (click)=\"toggleAboutSideBar()\">\n            <i class=\"large inverted info icon\"></i>\n        </a>\n\n    </div>\n\n</div>\n<br>\n\n<!-- the modal will emit an event and call the grid component to add the requested cell to the board -->\n<app-add-gadget-modal #addGadgetModal\n                      (addGadgetEvent)=\"emitBoardAddGadgetEvent($event)\">\n</app-add-gadget-modal>\n\n<app-configuration-modal #boardConfigModal\n                               (dashboardCreateEvent)=\"emitBoardCreateEvent($event)\"\n                               (dashboardEditEvent)=\"emitBoardEditEvent($event)\"\n                               (dashboardDeleteEvent)=\"emitBoardDeleteEvent($event)\"\n                               [dashboardList]=\"dashboardList\">\n\n\n</app-configuration-modal>\n\n\n<!-- side bar content -->\n<div class=\"ui sidebar inverted right vertical menu\" #notificationSideBar_tag>\n    <app-notification-modal></app-notification-modal>\n</div>\n\n<!-- side bar content -->\n<div class=\"ui sidebar inverted right vertical menu\" #aboutSideBar_tag>\n    <app-about-modal></app-about-modal>\n</div>\n\n\n<div class=\"ui sidebar inverted right vertical menu\" #layoutSideBar_tag>\n    <app-board-layout-manager-modal [layoutId]=\"layoutId\"\n                                    (boardLayoutChangeEvent)=\"emitBoardChangeLayoutEvent($event)\">\n    </app-board-layout-manager-modal>\n</div>\n\n"
  },
  {
    "path": "src/app/notification/notification-component.css",
    "content": "\n.components{\n    border-bottom: solid !important;\n    border-bottom-color: rgba(128, 128, 128, 0.69) !important;\n    border-bottom-width: thin !important;\n}\ntd.selected {\n    background-color: #4fa6d3 !important;\n    color: white;\n    font-weight: lighter;\n}\n\ntd{\n    line-height: 1.7;\n}\n\n.ui.table tr td{\n    border:none;\n}\n\n.ui.floating.label{\n\n}\ntr {\n    cursor: pointer;\n}"
  },
  {
    "path": "src/app/notification/notification-component.html",
    "content": "<!-- <div class=\"ui long modal\" #notificationModalTag> -->\n<br>\n<div class=\"header\">\n    <h2><span style=\"padding: 30px; color:white\">{{modalHeader}}</span></h2>\n</div>\n\n\n<!--todo this should be two tables, one for the top filters and another for the component specific filters -->\n<table class=\"ui inverted selectable celled table\">\n    <tbody>\n    <tr *ngFor=\"let item of notificationFilters; let idx = index\"\n        (click)=\"setSelectedNotificationFilter(item)\">\n        <td [ngClass]=\"{'selected': item.name == currentNotificationFilter.name, 'components': idx==1}\">\n            <div style=\"float:left;text-align:left\">{{item.name}}</div>\n            <div style=\"float:right;text-align: right\">{{item.count}}</div>\n        </td>\n    </tr>\n    </tbody>\n</table>\n\n<div>\n\n    <div *ngIf=\"currentNotificationFilter\">\n\n        <app-notification-detail></app-notification-detail>\n    </div>\n\n</div>\n\n\n\n"
  },
  {
    "path": "src/app/notification/notification-component.spec.ts",
    "content": "import { async, ComponentFixture, TestBed } from '@angular/core/testing';\n\nimport { NotificationComponent } from './notification-component';\n\ndescribe('NotificationComponent', () => {\n  let component: NotificationComponent;\n  let fixture: ComponentFixture<NotificationComponent>;\n\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      declarations: [ NotificationComponent ]\n    })\n    .compileComponents();\n  }));\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(NotificationComponent);\n    component = fixture.componentInstance;\n    fixture.detectChanges();\n  });\n\n  it('should create', () => {\n    expect(component).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "src/app/notification/notification-component.ts",
    "content": "import {AfterViewInit, Component, OnInit} from '@angular/core';\n\n\n@Component({\n\n    moduleId: module.id,\n    selector: 'app-notification-modal',\n    templateUrl: './notification-component.html',\n    styleUrls: ['./notification-component.css']\n})\nexport class NotificationComponent implements OnInit, AfterViewInit {\n\n    notificationFilters: any [] = [];\n    currentNotificationFilter = {\n        name: '',\n        count: 0\n    };\n\n    notificationModal: any;\n    modalHeader = 'Notifications';\n\n    constructor() {\n\n        this.notificationFilters.push({name: 'Unacknowledged', count: 4});\n        this.notificationFilters.push({name: 'All Notifications', count: 4});\n        this.notificationFilters.push({name: 'Trend Gadget', count: 4});\n        this.notificationFilters.push({name: 'CPU Gadget', count: 0});\n        this.setSelectedNotificationFilter({name: 'Unacknowledged', count: 4});\n\n    }\n\n    ngOnInit() {\n    }\n\n    ngAfterViewInit() {\n\n    }\n\n    setSelectedNotificationFilter(item) {\n\n        this.currentNotificationFilter = item;\n\n    }\n\n}\n"
  },
  {
    "path": "src/app/notification/notification-service.spec.ts",
    "content": "import { TestBed, inject } from '@angular/core/testing';\n\nimport { NotificationService } from './notification-service';\n\ndescribe('NotificationService', () => {\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      providers: [NotificationService]\n    });\n  });\n\n  it('should ...', inject([NotificationService], (service: NotificationService) => {\n    expect(service).toBeTruthy();\n  }));\n});\n"
  },
  {
    "path": "src/app/notification/notification-service.ts",
    "content": "import { Injectable } from '@angular/core';\n\n@Injectable()\nexport class NotificationService {\n\n  constructor() { }\n\n}\n"
  },
  {
    "path": "src/app/notification/notification.model.ts",
    "content": "export class Notification {\n    public id: number;\n    public name: string;\n    public description: string;\n    public state: string;\n    public icon: string;\n    public when: string;\n\n    constructor(name: string, description: string) {\n        this.name = name;\n        this.description = description;\n    }\n    setState(state: string) {\n        this.state = state;\n    }\n    getState() {\n        return this.state;\n    }\n\n    setIcon(icon: string) {\n        this.icon = icon;\n    }\n    getIcon() {\n        return this.icon;\n    }\n\n    setWhen(when: string) {\n        this.when = when;\n    }\n    getWhen() {\n        return this.when;\n    }\n\n}\n"
  },
  {
    "path": "src/app/notification/notification.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {NotificationComponent} from './notification-component';\nimport {NotificationService} from './notification-service';\nimport {NotificationDetailComponent} from './notificationDetail.component';\n\n@NgModule({\n    imports: [\n        CommonModule\n    ],\n    declarations: [NotificationComponent, NotificationDetailComponent],\n    providers: [NotificationService],\n    exports: [NotificationComponent]\n})\nexport class NotificationModule {\n}\n"
  },
  {
    "path": "src/app/notification/notificationDetail.component.ts",
    "content": "/**\n * Created by jayhamilton on 5/16/17.\n */\nimport {Component} from '@angular/core';\nimport {Notification} from './notification.model';\n\n@Component({\n    selector: 'app-notification-detail',\n    moduleId: module.id,\n    templateUrl: './notificationDetail.html'\n\n})\nexport class NotificationDetailComponent {\n\n\n    notifications: Notification[];\n\n    constructor() {\n\n        this.notifications = [];\n        let notification = new Notification('CPU Gadget', 'this is a cpu gadget error');\n        notification.setWhen((new Date()).toString());\n        this.notifications.push(notification);\n        notification = new Notification ('Trend Gadget', 'this is a trend gadget error2');\n        notification.setWhen((new Date()).toString());\n        this.notifications.push(notification);\n        notification = new Notification ('Disk Gadget', 'Disk 1 alert');\n        notification.setWhen((new Date()).toString());\n        this.notifications.push(notification);\n        notification = new Notification ('Disk Gadget', 'Disk 2 alert');\n        notification.setWhen((new Date()).toString());\n        this.notifications.push(notification);\n\n    }\n\n\n}\n"
  },
  {
    "path": "src/app/notification/notificationDetail.html",
    "content": "<h3>&nbsp;&nbsp;Details</h3>\n<table class=\"ui inverted table\">\n    <tr *ngFor=\"let notification of notifications\">\n        <td style=\"font-weight:100 !important;\">\n            <div>\n                {{notification.description}}\n                <br>\n                {{notification.when}}\n            </div>\n        </td>\n    </tr>\n</table>\n\n\n\n\n\n"
  },
  {
    "path": "src/app/routing.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {Routes, RouterModule} from '@angular/router';\nimport {AppComponent} from './app.component';\nimport {BoardComponent} from './board/board.component';\nimport {DetailComponent} from './detail/detail.component';\n\nexport const routes: Routes = [\n    {\n        path: '',\n        redirectTo: 'main-board',\n        pathMatch: 'full'\n    },\n    {\n        path: '',\n        component: AppComponent\n    },\n    {\n        path: 'main-board',\n        component: BoardComponent\n    },\n    {\n        path: 'detail',\n        component: DetailComponent,\n        runGuardsAndResolvers: 'always'\n    },\n\n\n];\n\n@NgModule({\n    imports: [RouterModule.forRoot(routes,{onSameUrlNavigation: 'reload'})],\n    exports: [RouterModule]\n})\nexport class RoutingModule {\n}\n\n"
  },
  {
    "path": "src/app/services/configuration-sample-boards-prod.model.ts",
    "content": "export const sampleBoardCollectionProd = {\n    \"board\":\n    [{\n        \"title\": \"Network Test\",\n        \"structure\": \"8\",\n        \"id\": 0,\n        \"boardInstanceId\": 1532575263046,\n        \"rows\": [{\n            \"columns\": [{\n                \"styleClass\": \"eight wide\",\n                \"gadgets\": [{\n                    \"componentType\": \"PortConnectionGadgetComponent\",\n                    \"name\": \"Port Connection Test\",\n                    \"description\": \"Test Connection To Endpoints.\",\n                    \"icon\": \"assets/images/response.png\",\n                    \"instanceId\": 1533516521962,\n                    \"tags\": [{\"facet\": \"Informational\", \"name\": \"port-connection\"}],\n                    \"config\": {\n                        \"propertyPages\": [{\n                            \"displayName\": \"Run\",\n                            \"groupId\": \"run\",\n                            \"position\": 10,\n                            \"properties\": [{\n                                \"value\": \"Connection Test\",\n                                \"key\": \"title\",\n                                \"label\": \"Title\",\n                                \"required\": false,\n                                \"order\": 1,\n                                \"controlType\": \"textbox\"\n                            }, {\n                                \"value\": \"\",\n                                \"key\": \"host\",\n                                \"label\": \"Host\",\n                                \"required\": false,\n                                \"order\": 1,\n                                \"controlType\": \"textbox\"\n                            }, {\n                                \"value\": \"\",\n                                \"key\": \"port\",\n                                \"label\": \"Port(s)\",\n                                \"required\": false,\n                                \"order\": 3,\n                                \"controlType\": \"dropdown\",\n                                \"options\": [{\n                                    \"key\": \"vSnap + vAdp (All Ports)\",\n                                    \"value\": \"8900,8080,22,111,20048,2049\"\n                                }, {\n                                    \"key\": \"SPP Single Appliance (All Ports)\",\n                                    \"value\": \"443,8900,22,111,20048,2049\"\n                                }, {\"key\": \"SPP (443)\", \"value\": \"443\"}, {\n                                    \"key\": \"SPP (8443)\",\n                                    \"value\": \"8443\"\n                                }, {\"key\": \"SPP (3000)\", \"value\": \"3000\"}, {\n                                    \"key\": \"LDAP (389)\",\n                                    \"value\": \"389\"\n                                }, {\"key\": \"LDAP (636)\", \"value\": \"636\"}, {\n                                    \"key\": \"VADP (8080)\",\n                                    \"value\": \"8080\"\n                                }, {\"key\": \"WinRM (5985)\", \"value\": \"5985\"}, {\n                                    \"key\": \"VSnap (8900)\",\n                                    \"value\": \"8900\"\n                                }, {\"key\": \"SSH (22)\", \"value\": \"22\"}, {\n                                    \"key\": \"ISCSI (3260)\",\n                                    \"value\": \"3260\"\n                                }, {\"key\": \"NFS (2049)\", \"value\": \"2049\"}, {\n                                    \"key\": \"NFS (20048)\",\n                                    \"value\": \"20048\"\n                                }, {\"key\": \"NFS (111)\", \"value\": \"111\"}, {\"key\": \"ESXI (902)\", \"value\": \"902\"}]\n                            }, {\n                                \"value\": 2,\n                                \"key\": \"instanceId\",\n                                \"label\": \"\",\n                                \"required\": false,\n                                \"order\": -1,\n                                \"controlType\": \"hidden\"\n                            }]\n                        }]\n                    },\n                    \"actions\": [{\"name\": \"Add\"}]\n                }]\n            }]\n        }]\n    }]\n};\n\n"
  },
  {
    "path": "src/app/services/configuration-sample-boards.model.ts",
    "content": "export const sampleBoardCollection = {\n    'board': [{\n        'title': 'Board Sample 1',\n        'structure': '3-6-3',\n        'id': 9,\n        'boardInstanceId': 1,\n        'rows': [\n            {\n                'columns': [\n                    {\n                        'styleClass': 'three wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'NewsGadgetComponent',\n                                'name': 'News',\n                                'description': \"What's new\",\n                                'icon': 'images/news.png',\n                                'instanceId': 1500253814523,\n                                'tags': [\n                                    {\n                                        'facet': 'Informational',\n                                        'name': 'news'\n                                    },\n                                    {\n                                        'facet': 'List',\n                                        'name': 'news'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'news',\n                                                    'key': 'endpoint',\n                                                    'label': 'News URL',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'News',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        'styleClass': 'six wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'CPUGadgetComponent',\n                                'name': 'CPU Chart',\n                                'description': 'Monitors CPU utilization for CDM.',\n                                'icon': 'images/cpu.png',\n                                'instanceId': 1499912922910,\n                                'tags': [\n                                    {\n                                        'facet': 'Performance',\n                                        'name': 'real-time'\n                                    },\n                                    {\n                                        'facet': 'Chart',\n                                        'name': 'bar'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'CPU Utilization',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 'Carlosappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 999,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Chart',\n                                            'groupId': 'chart',\n                                            'position': 11,\n                                            'properties': [\n                                                {\n                                                    'value': true,\n                                                    'key': 'chart_properties',\n                                                    'label': 'Show chart details',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'checkbox'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            },\n                            {\n                                'componentType': 'TrendGadgetComponent',\n                                'name': 'Trend',\n                                'description': 'General trends.',\n                                'icon': 'images/trend.png',\n                                'instanceId': 1499912901569,\n                                'tags': [\n                                    {\n                                        'facet': 'Performance',\n                                        'name': 'trend'\n                                    },\n                                    {\n                                        'facet': 'Chart',\n                                        'name': 'area'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'Devappliance - ECX',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Trend',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Chart',\n                                            'groupId': 'chart',\n                                            'position': 11,\n                                            'properties': [\n                                                {\n                                                    'value': true,\n                                                    'key': 'chart_properties',\n                                                    'label': 'Show chart details',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'checkbox'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        'styleClass': 'three wide',\n                        'gadgets': []\n                    }\n                ]\n            }\n        ]\n    }, {\n        'title': 'Board Sample 2',\n        'structure': '4-4-4-4/8-4-4',\n        'id': 8,\n        'boardInstanceId': 2,\n        'rows': [\n            {\n                'columns': [\n                    {\n                        'styleClass': 'four wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'StatisticGadgetComponent',\n                                'name': 'Statistic',\n                                'description': 'General statistic.',\n                                'icon': 'images/statistic.png',\n                                'instanceId': 1499912861630,\n                                'tags': [\n                                    {\n                                        'facet': 'Statistic',\n                                        'name': 'counter'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'database',\n                                                    'key': 'resource',\n                                                    'label': 'Resource',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dropdown',\n                                                    'options': [\n                                                        {\n                                                            'key': 'vm',\n                                                            'value': 'vm'\n                                                        },\n                                                        {\n                                                            'key': 'database',\n                                                            'value': 'database'\n                                                        },\n                                                        {\n                                                            'key': 'volume',\n                                                            'value': 'volume'\n                                                        },\n                                                        {\n                                                            'key': 'job',\n                                                            'value': 'job'\n                                                        }\n                                                    ]\n                                                },\n                                                {\n                                                    'value': 'Devappliance - ECX',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Statistic',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': true,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        'styleClass': 'four wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'StatisticGadgetComponent',\n                                'name': 'Statistic',\n                                'description': 'General statistic.',\n                                'icon': 'images/statistic.png',\n                                'instanceId': 1499912845375,\n                                'tags': [\n                                    {\n                                        'facet': 'Statistic',\n                                        'name': 'counter'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'vm',\n                                                    'key': 'resource',\n                                                    'label': 'Resource',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dropdown',\n                                                    'options': [\n                                                        {\n                                                            'key': 'vm',\n                                                            'value': 'vm'\n                                                        },\n                                                        {\n                                                            'key': 'database',\n                                                            'value': 'database'\n                                                        },\n                                                        {\n                                                            'key': 'volume',\n                                                            'value': 'volume'\n                                                        },\n                                                        {\n                                                            'key': 'job',\n                                                            'value': 'job'\n                                                        }\n                                                    ]\n                                                },\n                                                {\n                                                    'value': 'Carlosappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Statistic',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': true,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        'styleClass': 'four wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'StatisticGadgetComponent',\n                                'name': 'Statistic',\n                                'description': 'General statistic.',\n                                'icon': 'images/statistic.png',\n                                'instanceId': 1500251223835,\n                                'tags': [\n                                    {\n                                        'facet': 'Statistic',\n                                        'name': 'counter'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'volume',\n                                                    'key': 'resource',\n                                                    'label': 'Resource',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dropdown',\n                                                    'options': [\n                                                        {\n                                                            'key': 'vm',\n                                                            'value': 'vm'\n                                                        },\n                                                        {\n                                                            'key': 'database',\n                                                            'value': 'database'\n                                                        },\n                                                        {\n                                                            'key': 'volume',\n                                                            'value': 'volume'\n                                                        },\n                                                        {\n                                                            'key': 'job',\n                                                            'value': 'job'\n                                                        }\n                                                    ]\n                                                },\n                                                {\n                                                    'value': 'Carlosappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Statistic',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': true,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        'styleClass': 'four wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'StatisticGadgetComponent',\n                                'name': 'Statistic',\n                                'description': 'General statistic.',\n                                'icon': 'images/statistic.png',\n                                'instanceId': 1500251241829,\n                                'tags': [\n                                    {\n                                        'facet': 'Statistic',\n                                        'name': 'counter'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'job',\n                                                    'key': 'resource',\n                                                    'label': 'Resource',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dropdown',\n                                                    'options': [\n                                                        {\n                                                            'key': 'vm',\n                                                            'value': 'vm'\n                                                        },\n                                                        {\n                                                            'key': 'database',\n                                                            'value': 'database'\n                                                        },\n                                                        {\n                                                            'key': 'volume',\n                                                            'value': 'volume'\n                                                        },\n                                                        {\n                                                            'key': 'job',\n                                                            'value': 'job'\n                                                        }\n                                                    ]\n                                                },\n                                                {\n                                                    'value': 'Carlosappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Statistic',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': true,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    }\n                ]\n            },\n            {\n                'columns': [\n                    {\n                        'styleClass': 'eight wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'TrendLineGadgetComponent',\n                                'name': 'Realtime Performance',\n                                'description': 'IOPs and Network Bandwidth.',\n                                'icon': 'images/trend-line.png',\n                                'instanceId': 1500251340757,\n                                'tags': [\n                                    {\n                                        'facet': 'Performance',\n                                        'name': 'trend'\n                                    },\n                                    {\n                                        'facet': 'Chart',\n                                        'name': 'line'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'Devappliance - ECX',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Performance',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Chart',\n                                            'groupId': 'chart',\n                                            'position': 11,\n                                            'properties': [\n                                                {\n                                                    'value': true,\n                                                    'key': 'chart_properties',\n                                                    'label': 'Show chart details',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'checkbox'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            },\n                            {\n                                'componentType': 'ServiceListGadgetComponent',\n                                'name': 'Service Status',\n                                'description': 'Monitors Service Status',\n                                'icon': 'images/service.png',\n                                'instanceId': 1500343727872,\n                                'tags': [\n                                    {\n                                        'facet': 'List',\n                                        'name': 'health'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'Devappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Service Status',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 999,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'List',\n                                            'groupId': 'chart',\n                                            'position': 11,\n                                            'properties': [\n                                                {\n                                                    'value': true,\n                                                    'key': 'chart_properties',\n                                                    'label': 'Show chart details',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'checkbox'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        'styleClass': 'four wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'DiskGadgetComponent',\n                                'name': 'Disk Utilization',\n                                'description': 'Disk consumption information for ECX.',\n                                'icon': 'images/donut.png',\n                                'instanceId': 1500253741130,\n                                'tags': [\n                                    {\n                                        'facet': 'Chart',\n                                        'name': 'pie'\n                                    },\n                                    {\n                                        'facet': 'Performance',\n                                        'name': 'storage'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'Carlosappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 4,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Disk Consumption',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 50,\n                                                    'key': 'threshold',\n                                                    'label': 'Consumed Threshold',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'number'\n                                                },\n                                                {\n                                                    'value': 'g3g3egegre',\n                                                    'key': 'diskid',\n                                                    'label': 'Disk Id',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dropdown',\n                                                    'options': [\n                                                        {\n                                                            'key': '2344112gdfgdfg',\n                                                            'value': '2344112gdfgdfg'\n                                                        },\n                                                        {\n                                                            'key': 'g3g3egegre',\n                                                            'value': 'g3g3egegre'\n                                                        },\n                                                        {\n                                                            'key': '8435f34',\n                                                            'value': '8435f34'\n                                                        }\n                                                    ]\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Thresholds',\n                                            'groupId': 'threshold',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 30,\n                                                    'key': 'frequency',\n                                                    'label': 'Frequency',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'number'\n                                                },\n                                                {\n                                                    'value': 30,\n                                                    'key': 'retentionH',\n                                                    'label': 'Retention High',\n                                                    'required': false,\n                                                    'order': 4,\n                                                    'controlType': 'number'\n                                                },\n                                                {\n                                                    'value': 180,\n                                                    'key': 'retentionL',\n                                                    'label': 'Retention Low',\n                                                    'required': false,\n                                                    'order': 4,\n                                                    'controlType': 'number'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Chart',\n                                            'groupId': 'chart',\n                                            'position': 11,\n                                            'properties': [\n                                                {\n                                                    'value': true,\n                                                    'key': 'chart_properties',\n                                                    'label': 'Show chart details',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'checkbox'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    },\n                    {\n                        'styleClass': 'four wide',\n                        'gadgets': [\n                            {\n                                'componentType': 'DiskGadgetComponent',\n                                'name': 'Disk Utilization',\n                                'description': 'Disk consumption information for ECX.',\n                                'icon': 'images/donut.png',\n                                'instanceId': 1500252483066,\n                                'tags': [\n                                    {\n                                        'facet': 'Chart',\n                                        'name': 'pie'\n                                    },\n                                    {\n                                        'facet': 'Performance',\n                                        'name': 'storage'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'Carlosappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 4,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Disk Consumption',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 50,\n                                                    'key': 'threshold',\n                                                    'label': 'Consumed Threshold',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'number'\n                                                },\n                                                {\n                                                    'value': 'g3g3egegre',\n                                                    'key': 'diskid',\n                                                    'label': 'Disk Id',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dropdown',\n                                                    'options': [\n                                                        {\n                                                            'key': '2344112gdfgdfg',\n                                                            'value': '2344112gdfgdfg'\n                                                        },\n                                                        {\n                                                            'key': 'g3g3egegre',\n                                                            'value': 'g3g3egegre'\n                                                        },\n                                                        {\n                                                            'key': '8435f34',\n                                                            'value': '8435f34'\n                                                        }\n                                                    ]\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Thresholds',\n                                            'groupId': 'threshold',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 30,\n                                                    'key': 'frequency',\n                                                    'label': 'Frequency',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'number'\n                                                },\n                                                {\n                                                    'value': 30,\n                                                    'key': 'retentionH',\n                                                    'label': 'Retention High',\n                                                    'required': false,\n                                                    'order': 4,\n                                                    'controlType': 'number'\n                                                },\n                                                {\n                                                    'value': 180,\n                                                    'key': 'retentionL',\n                                                    'label': 'Retention Low',\n                                                    'required': false,\n                                                    'order': 4,\n                                                    'controlType': 'number'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Chart',\n                                            'groupId': 'chart',\n                                            'position': 11,\n                                            'properties': [\n                                                {\n                                                    'value': true,\n                                                    'key': 'chart_properties',\n                                                    'label': 'Show chart details',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'checkbox'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            },\n                            {\n                                'componentType': 'TrendGadgetComponent',\n                                'name': 'Trend',\n                                'description': 'General trends.',\n                                'icon': 'images/trend.png',\n                                'instanceId': 1500252536414,\n                                'tags': [\n                                    {\n                                        'facet': 'Performance',\n                                        'name': 'trend'\n                                    },\n                                    {\n                                        'facet': 'Chart',\n                                        'name': 'area'\n                                    }\n                                ],\n                                'config': {\n                                    'propertyPages': [\n                                        {\n                                            'displayName': 'Run',\n                                            'groupId': 'run',\n                                            'position': 10,\n                                            'properties': [\n                                                {\n                                                    'value': 'Carlosappliance - Process Monitor',\n                                                    'key': 'endpoint',\n                                                    'label': 'API Endpoints',\n                                                    'required': false,\n                                                    'order': 2,\n                                                    'controlType': 'dynamicdropdown'\n                                                },\n                                                {\n                                                    'value': 'Trend',\n                                                    'key': 'title',\n                                                    'label': 'Title',\n                                                    'required': false,\n                                                    'order': 1,\n                                                    'controlType': 'textbox'\n                                                },\n                                                {\n                                                    'value': 2,\n                                                    'key': 'instanceId',\n                                                    'required': false,\n                                                    'order': -1,\n                                                    'controlType': 'hidden'\n                                                }\n                                            ]\n                                        },\n                                        {\n                                            'displayName': 'Chart',\n                                            'groupId': 'chart',\n                                            'position': 11,\n                                            'properties': [\n                                                {\n                                                    'value': true,\n                                                    'key': 'chart_properties',\n                                                    'label': 'Show chart details',\n                                                    'required': false,\n                                                    'order': 3,\n                                                    'controlType': 'checkbox'\n                                                }\n                                            ]\n                                        }\n                                    ]\n                                }\n                            }\n                        ]\n                    }\n                ]\n            }\n        ]\n    }\n    ]\n};\n\n"
  },
  {
    "path": "src/app/services/configuration-sample-default-board.ts",
    "content": "export const  defaultBoard = {\n    title: 'Dashboard',\n    structure: '6-6',\n    id: 5,\n    boardInstanceId: 0,\n    rows: [\n        {\n            columns: [\n                {\n                    styleClass: 'six wide',\n                    gadgets: []\n                },\n                {\n                    styleClass: 'six wide',\n                    gadgets: []\n                }\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": "src/app/services/configuration.service.ts",
    "content": "/**\n * Created by jayhamilton on 2/7/17.\n */\nimport {Injectable} from '@angular/core';\nimport {HttpClient, HttpHeaders} from '@angular/common/http';\nimport {EMPTY, Observable} from 'rxjs';\nimport {defaultBoard} from './configuration-sample-default-board';\nimport {sampleBoardCollectionProd} from './configuration-sample-boards-prod.model';\nimport {sampleBoardCollection} from './configuration-sample-boards.model';\nimport {environment} from '../../environments/environment';\n\n\n@Injectable()\nexport class ConfigurationService {\n    model: any; // todo review this object closely\n    currentModel: any; // this object helps with updates to property page values\n    demo = true;\n    env: any;\n\n    defaultBoard: any;\n    sampleBoardCollection: any;\n    sampleBoardCollectionProd:any;\n\n    /**\n     * todo - fix this hard coded store\n     * @type {string}\n     */\n    remoteConfigurationRepository = '';\n\n    constructor(private _http: HttpClient) {\n\n        Object.assign(this, {defaultBoard});\n        Object.assign(this, {sampleBoardCollection});\n        Object.assign(this, {sampleBoardCollectionProd});\n        this.env = environment;\n        this.seedLocalStorageWithSampleBoardCollection();\n    }\n\n    private seedLocalStorageWithSampleBoardCollection() {\n\n        if (localStorage.getItem('board') === null) {\n\n\n            if (this.env.production == true) {\n\n                localStorage.setItem('board', JSON.stringify(this.sampleBoardCollectionProd));\n            } else {\n                localStorage.setItem('board', JSON.stringify(this.sampleBoardCollection));\n            }\n        }\n    }\n\n    public getBoardByTitle(title: string) {\n\n        if (this.demo) {\n\n            return new Observable(observer => {\n                const board_collection = JSON.parse(localStorage.getItem('board'));\n\n                let data = '';\n                board_collection['board'].forEach(boardModel => {\n\n                    if (boardModel.title === title) {\n                        data = boardModel;\n                    }\n                });\n                observer.next(data);\n                return () => {\n                };\n            });\n        } else {\n\n            return this._http.get(this.remoteConfigurationRepository + '/' + name);\n        }\n    }\n\n    public getBoards() {\n\n        if (this.demo) {\n            return new Observable(observer => {\n                let data = JSON.parse(localStorage.getItem('board'));\n                if (!data) {\n                    data = {board: []};\n                }\n                observer.next(data.board);\n                return () => {\n                };\n            });\n\n        } else {\n            /**\n             * todo - this call is based on an internal representation (admin console) of something called a store.\n             * That concept requires refactoring.\n             */\n            return this._http.get(this.remoteConfigurationRepository);\n        }\n    }\n\n    public saveBoard(board: any) {\n\n        this.model = board;\n\n        if (Object.keys(board).length === 0 && board.constructor === Object) {\n            return  EMPTY;\n        }\n\n        if (this.demo) {\n            return new Observable(observer => {\n                let board_collection;\n\n                // find and remove board from storage\n                this.deleteBoardFromLocalStore(board.title);\n\n                // get a collection object and add board to it\n                if ((board_collection = JSON.parse(localStorage.getItem('board'))) == null) {\n\n                    board_collection = {\n                        board: []\n                    };\n                }\n                board_collection['board'].push(board);\n\n                // save\n                localStorage.setItem('board', JSON.stringify(board_collection));\n\n                observer.next({});\n\n                return () => {\n                };\n\n            });\n\n        } else {\n\n            /**\n             * todo - a delete must happen here\n             *\n             */\n            const httpOptions = {\n                headers: new HttpHeaders({\n                    'Content-Type': 'application/json'\n                })\n            };\n\n            return this._http.post(this.remoteConfigurationRepository + '?id=' + board.title, JSON.stringify(board), httpOptions);\n        }\n    }\n\n    private delete(board_collection: any) {\n\n        localStorage.removeItem('board');\n        localStorage.setItem('board', JSON.stringify(board_collection));\n\n    }\n\n    private deleteBoardFromLocalStore(boardTitle: string) {\n        const board_collection = JSON.parse(localStorage.getItem('board'));\n\n        let index;\n        if (board_collection && (index = board_collection['board'].findIndex(item => {\n            return item.title === boardTitle;\n        })) >= 0) {\n\n            board_collection['board'].splice(index, 1);\n\n            this.delete(board_collection);\n\n        }\n    }\n\n    public deleteBoard(boardTitle: string) {\n\n        if (this.demo) {\n\n            return new Observable(observer => {\n\n                this.deleteBoardFromLocalStore(boardTitle);\n\n                observer.next({});\n                return () => {\n                };\n\n            });\n\n        } else {\n\n            return this._http.delete(this.remoteConfigurationRepository + '/' + boardTitle);\n        }\n    }\n\n    public getDefaultBoard() {\n\n        return new Observable(observer => {\n            observer.next(this.defaultBoard);\n            return () => {\n            };\n        });\n    }\n\n\n    /*\n     when a gadget instance's property page is updated and saved, the change gets communicated to all\n     gadgets. The gadget instance id that caused the change will update their current instance. todo - this might be able to be\n     improved. For now the utility of this approach allows the configuration service to capture the property page change in a way\n     that allows us to update the persisted board model.\n     */\n    notifyGadgetOnPropertyChange(gadgetConfig: string, instanceId: number) {\n\n        this.savePropertyPageConfigurationToStore(gadgetConfig, instanceId);\n    }\n\n\n    setCurrentModel(_currentModel: any) {\n        this.currentModel = _currentModel;\n    }\n\n    savePropertyPageConfigurationToStore(gadgetConfig: string, instanceId: number) {\n\n        this.currentModel.rows.forEach(row => {\n\n            row.columns.forEach(column => {\n\n                if (column.gadgets) {\n                    column.gadgets.forEach(gadget => {\n                        this.updateProperties(gadgetConfig, gadget, instanceId);\n\n                    });\n                }\n            });\n        });\n\n        this.saveBoard(this.currentModel).subscribe(result => {\n\n                /**\n                 * todo - create popup/toast to show configuration saved message\n                 */\n                console.debug('The following configuration model was saved!');\n\n            },\n            error => console.error('Error' + error),\n            () => console.debug('Saving configuration to store!'));\n\n\n    }\n\n    updateProperties(updatedProperties: any, gadget: any, instanceId: number) {\n\n        const updatedPropsObject = JSON.parse(updatedProperties);\n\n        if (gadget.instanceId === instanceId) {\n\n            gadget.config.propertyPages.forEach(function (propertyPage) {\n\n                for (let x = 0; x < propertyPage.properties.length; x++) {\n\n                    for (const prop in updatedPropsObject) {\n                        if (updatedPropsObject.hasOwnProperty(prop)) {\n                            if (prop === propertyPage.properties[x].key) {\n                                propertyPage.properties[x].value = updatedPropsObject[prop];\n                            }\n                        }\n                    }\n                }\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/app/services/runtime.service.ts",
    "content": "/**\n * Created by jayhamilton on 1/18/17.\n */\nimport {Injectable} from '@angular/core';\nimport {throwError,Observable} from 'rxjs';\nimport {catchError} from \"rxjs/operators\";\nimport {ErrorHandler} from '../error/error-handler';\nimport {HttpClient, HttpErrorResponse, HttpParams} from '@angular/common/http';\nimport {environment} from '../../environments/environment';\n\n\n@Injectable()\nexport class RuntimeService {\n\n    watsonMicroserviceURL: string;\n    connectivityTestURL: string;\n    serviceVersionURL: string;\n    testURL = \"http://localhost:8080\";\n\n    static handleError(err: HttpErrorResponse | any) {\n\n        const errMsg: any = {\n            status: '-1',\n            statusText: '',\n            resource: ''\n        };\n\n\n        if (err.error instanceof Error) {\n            errMsg.statusText = err.error.message;\n            console.log('Client error');\n\n        } else {\n            errMsg.status = err.status;\n            errMsg.statusText = 'A backend error occurred. In all likelihood the server/api service is not running.';\n            errMsg.resource = err.url;\n\n        }\n\n        return throwError(ErrorHandler.getErrorObject(errMsg));\n\n    }\n\n    constructor(private _http: HttpClient) {\n        this.configure();\n    }\n\n    configure() {\n\n        if (environment.production) {\n            this.watsonMicroserviceURL = '/classify';\n            this.connectivityTestURL = '/connectTest';\n            this.serviceVersionURL = '/version'\n        } else {\n            this.connectivityTestURL = this.testURL + '/connectTest';\n            this.watsonMicroserviceURL = this.testURL + '/classify';\n            this.serviceVersionURL = this.testURL + '/version';\n        }\n\n    }\n\n    testURLResponse(url: string) {\n        return this._http.get(url, {responseType: 'text'})\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n\n    }\n\n    testConnectivity(host: string, port: string) {\n\n        let p = new HttpParams();\n        p = p.append('host', host);\n        p = p.append('port', port);\n\n        return this._http.get(this.connectivityTestURL, {params: p})\n            .pipe(\n                catchError(RuntimeService.handleError)\n            );\n\n    }\n\n    /**\n     * Wit AI can be called directly from a web server using JSONP\n     * @param {string} aiStatement\n     * @returns {Observable<any>}\n     */\n    callWitAI(aiStatement: string) {\n        console.log('running WitAi');\n\n        if (!environment.production) {\n\n            let p = new HttpParams();\n            if (!localStorage.getItem('Wit.aiToken')) {\n                return;\n            }\n\n            p = p.append('v', '20171128');\n            p = p.append('q', aiStatement);\n            p = p.append('access_token', localStorage.getItem('Wit.aiToken'));\n\n            return this._http.jsonp('https://api.wit.ai/message?' + p.toString(),\n                'callback'\n            ).pipe(\n                catchError(RuntimeService.handleError)\n            );\n        }\n    }\n\n    callback(data) {\n        // console.log(data);\n\n    }\n\n    /**\n     * Watson does not support JSONP for some of their APIs. This call relies on a backend that implements\n     * a Watson SDK. Im my configuration I am using a Spring Boot backend with a simple REST API which calls into\n     * the Watson JAVA SDK. The SDK requires a user, password and classifier, which is managed by the board configuration.\n     * Here is what the backend test SDK code looks like.\n\n     @RestController\n     class WatsonClassifier{\n     .......\n\n     @CrossOrigin\n     @RequestMapping(\"/classify\")\n     Classification processWatson(@RequestParam(value = \"userid\", defaultValue = \"\")\n     String userid, @RequestParam(value = \"password\", defaultValue = \"\") String password,\n     @RequestParam(value = \"classifier_id\", defaultValue = \"\") String classifierId,\n     @RequestParam(value = \"data\", defaultValue = \"\") String data) {\n\n        NaturalLanguageClassifier service = new NaturalLanguageClassifier();\n        service.setUsernameAndPassword(userid, password);\n        Classification classification = service.classify(classifierId, data).execute();\n        return classification;\n\n      }\n     }\n     *\n     * @param {string} aiStatement\n     * @returns {Observable<any>}\n     */\n    callWatsonAI(aiStatement: string) {\n        console.log('running Watson');\n\n\n        if (!localStorage.getItem('ibmwatsoncid')) {\n            return;\n        }\n\n        let p = new HttpParams();\n        p = p.append('userid', localStorage.getItem('ibmwatsonuid'));\n        p = p.append('password', localStorage.getItem('ibmwatsonpwd'));\n        p = p.append('classifier_id', localStorage.getItem('ibmwatsoncid'));\n        p = p.append('data', aiStatement);\n\n\n        return this._http.get(this.watsonMicroserviceURL, {\n            params: p\n        }).pipe(\n            catchError(RuntimeService.handleError)\n        );\n\n    }\n}\n"
  },
  {
    "path": "src/app/services/websocket-service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {Observable} from 'rxjs';\n\n\n@Injectable()\nexport class ObservableWebSocketService {\n\n    ws: WebSocket;\n\n    createObservableWebSocket(url: string): Observable<any> {\n\n        this.ws = new WebSocket(url);\n\n        return new Observable(observer => {\n\n            this.ws.onmessage = (event) => observer.next(event.data);\n            this.ws.onerror = (event) => observer.error(event);\n            this.ws.onclose = (event) => observer.complete();\n        });\n\n    }\n\n    sendMessage(message: string) {\n        this.ws.send(message);\n    }\n\n}\n"
  },
  {
    "path": "src/app/toast/message.ts",
    "content": "export class Message {\n\n    id: number;\n    content: string;\n    style: string;\n    dismissed = false;\n\n    constructor(content, id, style?) {\n        this.content = content;\n        this.style = style || 'info';\n        this.id = id;\n    }\n\n}\n"
  },
  {
    "path": "src/app/toast/reverse.pipe.spec.ts",
    "content": "import { ReversePipe } from './reverse.pipe';\n\ndescribe('ReversePipe', () => {\n  it('create an instance', () => {\n    const pipe = new ReversePipe();\n    expect(pipe).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "src/app/toast/reverse.pipe.ts",
    "content": "import {Pipe, PipeTransform} from '@angular/core';\nimport {filter, reverse} from 'lodash';\n\n@Pipe({\n    name: 'reverse'\n})\nexport class ReversePipe implements PipeTransform {\n\n    transform(value: any, args?: any): any {\n\n        value = filter(value, ['dismissed', false]);\n        return reverse(value);\n    }\n\n}\n"
  },
  {
    "path": "src/app/toast/toast.component.css",
    "content": ".wrapper {\n    position: absolute;\n    top: 50px;\n    right: 10px;\n    width: 400px;\n    z-index: 1000;\n}\n\n.toast {\n    width: inherit;\n}\n\n.toast-icon {\n\n    background-color: #384b5f;\n    text-align: center;\n\n}\n\n.ui[class*=\"top right attached\"].label {\n    background-color: transparent;\n}\n\n.toast-message{\n    height: 40px;\n    display:table-cell;\n    vertical-align: middle;\n}"
  },
  {
    "path": "src/app/toast/toast.component.html",
    "content": "<div class=\"wrapper\">\n    <div class=\"toast\" *ngFor=\"let message of messages\">\n        <table class=\"ui table\" (click)=\"dismiss(message.id)\" [@showHide] *ngIf=\"message.dismissed == false\">\n            <tr>\n                <td class=\"toast-icon\" width='50px'><i\n                        class=\"large inverted check icon\"></i></td>\n                <td>\n                    <div class=\"toast-message\">\n                        {{message.content}}\n                    </div>\n                </td>\n            </tr>\n        </table>\n    </div>\n</div>"
  },
  {
    "path": "src/app/toast/toast.component.spec.ts",
    "content": "import { async, ComponentFixture, TestBed } from '@angular/core/testing';\n\nimport { ToastComponent } from './toast.component';\n\ndescribe('ToastComponent', () => {\n  let component: ToastComponent;\n  let fixture: ComponentFixture<ToastComponent>;\n\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      declarations: [ ToastComponent ]\n    })\n    .compileComponents();\n  }));\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(ToastComponent);\n    component = fixture.componentInstance;\n    fixture.detectChanges();\n  });\n\n  it('should create', () => {\n    expect(component).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "src/app/toast/toast.component.ts",
    "content": "import {Component, OnInit} from '@angular/core';\nimport {ToastService} from './toast.service';\nimport {Message} from './message';\nimport {animate, style, transition, trigger} from '@angular/animations';\nimport {timer} from 'rxjs';\n\n\n@Component({\n    selector: 'app-toast',\n    templateUrl: './toast.component.html',\n    styleUrls: ['./toast.component.css'],\n    animations: [\n\n        trigger('showHide', [\n            transition(':enter', [\n                style({opacity: 0}),\n                animate('500ms', style({opacity: 1}))\n            ]),\n            transition(':leave', [\n                style({opacity: 1}),\n                animate('500ms', style({opacity: 0}))\n            ])\n        ])]\n})\nexport class ToastComponent implements OnInit {\n\n    messages: Array<Message>;\n\n    constructor(private _toastService: ToastService) {\n    }\n\n\n    ngOnInit() {\n\n        this.messages = this._toastService.getMessages();\n\n\n        timer(7000, 7000).subscribe(t => {\n\n            this.messages.forEach(message => {\n\n                this.dismiss(message.id);\n\n            });\n        });\n\n    }\n\n    dismiss(id) {\n        this._toastService.dismissMessage(id);\n    }\n\n}\n"
  },
  {
    "path": "src/app/toast/toast.module.ts",
    "content": "import {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {ToastComponent} from './toast.component';\nimport {ReversePipe} from './reverse.pipe';\nimport {ToastService} from './toast.service';\n\n@NgModule({\n    imports: [\n        CommonModule\n    ],\n    declarations: [ToastComponent, ReversePipe],\n    providers: [ToastService],\n    exports: [ToastComponent]\n})\nexport class ToastModule {\n}\n"
  },
  {
    "path": "src/app/toast/toast.service.spec.ts",
    "content": "import { TestBed, inject } from '@angular/core/testing';\n\nimport { ToastService } from './toast.service';\n\ndescribe('ToastService', () => {\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      providers: [ToastService]\n    });\n  });\n\n  it('should be created', inject([ToastService], (service: ToastService) => {\n    expect(service).toBeTruthy();\n  }));\n});\n"
  },
  {
    "path": "src/app/toast/toast.service.ts",
    "content": "import {Injectable} from '@angular/core';\nimport {Message} from './message';\n\n@Injectable()\nexport class ToastService {\n\n    messages: Array<Message> = [];\n\n    constructor() {\n    }\n\n    getMessages() {\n        return this.messages;\n    }\n\n    sendMessage(content, style) {\n\n        const message = new Message(content, this.messages.length + 1, style);\n        this.messages.push(message);\n\n    }\n\n    dismissMessage(messageKey) {\n\n        this.purgeDismissedMessages();\n\n        this.messages.forEach(message => {\n            if (message.id === messageKey) {\n                message.dismissed = true;\n            }\n        });\n    }\n\n    purgeDismissedMessages  () {\n        this.messages.forEach(function (message, index, object) {\n\n            if (message.dismissed) {\n                object.splice(index, 1);\n            }\n        });\n    }\n\n\n}\n"
  },
  {
    "path": "src/app/typeahead-input/styles.css",
    "content": "\n.full-width {\n    width: 100%;\n}\n/deep/ .ui.menu .item>.input input{\n    font-size: 1.1em !important;\n}\n/deep/ .mat-form-field-underline{\n    height: 0 !important;\n}"
  },
  {
    "path": "src/app/typeahead-input/typeahead-input.component.ts",
    "content": "import {Component, ElementRef, EventEmitter, Input, Output} from '@angular/core';\nimport {RuntimeService} from '../services/runtime.service';\n\n/**\n * Created by jayhamilton on 2/26/17.\n */\n\n@Component({\n    moduleId: module.id,\n    selector: 'app-typeahead-input',\n    templateUrl: './view.html',\n    styleUrls: ['./styles.css'],\n})\nexport class TypeAheadInputComponent {\n\n    @Input() searchList: string[];\n    @Input() placeHolderText;\n    @Input() typeAheadIsInMenu: boolean;\n    @Output() selectionEvent = new EventEmitter<string>();\n    @Output() ArtificialIntelligenceEventEmitter: EventEmitter<any> = new EventEmitter<any>();\n\n    requestCounter = 0;\n    maxAttempts = 5;\n\n    public query = '';\n    public filteredList = [];\n    public elementRef;\n\n    constructor(myElement: ElementRef, private _runtimeService: RuntimeService) {\n        this.elementRef = myElement;\n\n    }\n\n    filter() {\n        if (this.query !== '') {\n            this.filteredList = this.searchList.filter(function (el) {\n                return el.toLowerCase().indexOf(this.query.toLowerCase()) > -1;\n            }.bind(this));\n        } else {\n            this.filteredList = [];\n        }\n        this.selectionEvent.emit(this.query);\n\n        this.requestCounter++;\n        if (this.requestCounter === this.maxAttempts) {\n\n            this.processAIString(this.query);\n            this.requestCounter = 0;\n        }\n    }\n\n    select(item) {\n        this.query = item;\n        this.filteredList = [];\n        this.selectionEvent.emit(item);\n    }\n\n    processAIString(aiStatement: string) {\n\n        console.log('Processing statement: ' + aiStatement);\n\n        const engine = localStorage.getItem('ai_engine');\n\n        if (engine.localeCompare('watson') === 0) {\n            this._runtimeService.callWatsonAI(aiStatement).subscribe(data => {\n                this.ArtificialIntelligenceEventEmitter.emit(this.getAIIntentFromWatson(data));\n            });\n        }\n        if (engine.localeCompare('witai') === 0) {\n            this._runtimeService.callWitAI(aiStatement).subscribe(data => {\n                this.ArtificialIntelligenceEventEmitter.emit(this.getAIIntentFromWitAI(data));\n            });\n        }\n    }\n\n    getAIIntentFromWitAI(aiObject: any) {\n\n        let operation = '';\n        let confidence = 0;\n\n        if (aiObject && aiObject.entities) {\n            if (aiObject.entities.intent && aiObject.entities.intent.length) {\n                operation = aiObject.entities.intent[0].value;\n                confidence = aiObject.entities.intent[0].confidence;\n            }\n        }\n\n        return {\n            'operation': operation,\n            'confidence': confidence\n        };\n    }\n\n    getAIIntentFromWatson(aiObject: any) {\n\n        let operation = '';\n        let confidence = 0;\n\n        if (aiObject && aiObject.classes) {\n            if (aiObject.classes && aiObject.classes.length) {\n                operation = aiObject.classes[0].name;\n                confidence = aiObject.classes[0].confidence;\n            }\n        }\n\n        return {\n            'operation': operation,\n            'confidence': confidence\n        };\n    }\n}\n"
  },
  {
    "path": "src/app/typeahead-input/typeahead-input.module.ts",
    "content": "import {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\n\nimport {TypeAheadInputComponent} from './typeahead-input.component';\nimport {FormsModule} from '@angular/forms';\n\n\n@NgModule({\n    imports: [\n        CommonModule,\n        FormsModule\n\n    ],\n    declarations: [\n        TypeAheadInputComponent\n    ],\n    providers: [\n    ],\n    exports: [\n        TypeAheadInputComponent\n    ]\n})\nexport class TypeAheadInputModule {\n}\n\n"
  },
  {
    "path": "src/app/typeahead-input/view.html",
    "content": "\n<div class=\"ui fluid transparent icon input\" [ngClass]=\"{inverted:typeAheadIsInMenu == true}\">\n    <input type=\"text\" width=\"100%\" placeholder={{placeHolderText}} [(ngModel)]=query (keyup)=filter()>\n    <i *ngIf=\"!query\"  class=\"large grey search icon\"></i> <i *ngIf=\"query\"  class=\"large grey remove link icon\" (click)=\"query=''\"></i>\n</div>\n\n<div class='suggestions' *ngIf='filteredList.length > 0'>\n\n    <ul style='list-style-type:none; background: white; border-radius: 7px;'>\n        <li style='padding:5px' *ngFor='let item of filteredList'>\n            <a (click)='select(item)'>{{item}}</a>\n        </li>\n    </ul>\n</div>\n"
  },
  {
    "path": "src/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "src/assets/api/chart-mock-bar-model.json",
    "content": "[\n  {\n    \"name\": \"metric 1\",\n    \"series\": [\n\n      {\n        \"name\": \"available\",\n        \"value\": 25\n      },{\n        \"name\": \"used\",\n        \"value\": 75\n      }\n    ]\n  },\n  {\n    \"name\": \"metric 2\",\n    \"series\": [\n\n      {\n        \"name\": \"available\",\n        \"value\": 77\n      },{\n        \"name\": \"used\",\n        \"value\": 23\n      }\n\n    ]\n  }\n]"
  },
  {
    "path": "src/assets/api/chart-mock-bubble-model.json",
    "content": "[\n  {\n    \"name\": \"Germany\",\n    \"series\": [\n      {\n        \"name\": \"2010\",\n        \"x\": 40632,\n        \"y\": 80.3,\n        \"r\": 80.4\n      },\n      {\n        \"name\": \"2000\",\n        \"x\": 36953,\n        \"y\": 80.3,\n        \"r\": 78\n      },\n      {\n        \"name\": \"1990\",\n        \"x\": 31476,\n        \"y\": 75.4,\n        \"r\": 79\n      }\n    ]\n  },\n  {\n    \"name\": \"USA\",\n    \"series\": [\n      {\n        \"name\": \"2010\",\n        \"x\": 49737,\n        \"y\": 78.8,\n        \"r\": 310\n      },\n      {\n        \"name\": \"2000\",\n        \"x\": 45986,\n        \"y\": 76.9,\n        \"r\": 283\n      },\n      {\n        \"name\": \"1990\",\n        \"x\": 3706,\n        \"y\": 75.4,\n        \"r\": 253\n      }\n    ]\n  },\n  {\n    \"name\": \"France\",\n    \"series\": [\n      {\n        \"name\": \"2010\",\n        \"x\": 36745,\n        \"y\": 81.4,\n        \"r\": 63\n      },\n      {\n        \"name\": \"2000\",\n        \"x\": 34774,\n        \"y\": 79.1,\n        \"r\": 59.4\n      },\n      {\n        \"name\": \"1990\",\n        \"x\": 29476,\n        \"y\": 77.2,\n        \"r\": 56.9\n      }\n    ]\n  },\n  {\n    \"name\": \"United Kingdom\",\n    \"series\": [\n      {\n        \"name\": \"2010\",\n        \"x\": 36240,\n        \"y\": 80.2,\n        \"r\": 62.7\n      },\n      {\n        \"name\": \"2000\",\n        \"x\": 32543,\n        \"y\": 77.8,\n        \"r\": 58.9\n      },\n      {\n        \"name\": \"1990\",\n        \"x\": 26424,\n        \"y\": 75.7,\n        \"r\": 57.1\n      }\n    ]\n  }\n]\n\n\n\n"
  },
  {
    "path": "src/assets/api/chart-mock-pie-model.json",
    "content": "[\n  {\n    \"name\": \"a\",\n    \"value\": 45\n  },\n  {\n    \"name\": \"b\",\n    \"value\": 344\n  },\n  {\n    \"name\": \"c\",\n    \"value\": 75\n  },\n  {\n    \"name\": \"d\",\n    \"value\": 23\n  }\n\n]"
  },
  {
    "path": "src/assets/api/connection-model.json",
    "content": "[\n  {\n    \"event\": \"unreachable\",\n    \"title\": \"Network is unreachable\",\n    \"summary\": \"The application failed to connect to the host due to inability to reach the host.\",\n    \"solution\": [\n      {\n        \"cause\": \"The target address may be IPV6.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Contact support to review this issue.\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"There may be a stale entry within the DNS server.\",\n        \"action\": [\n          {\n            \"id\": 2,\n            \"task\": \"You may want to contact your network administrator to see if the issue is related to a stale DNS entries.\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"General connectivity issue.\",\n        \"action\": [\n          {\n            \"id\": 2,\n            \"task\": \"Verify your network connections, proxies and firewalls.\"\n          }\n        ]\n      }\n    ]\n  },{\n    \"event\": \"time-out\",\n    \"title\": \"Network request timed out\",\n    \"summary\": \"The application link was able to contact the remote application but could not establish a connection.\",\n    \"solution\": [\n      {\n        \"cause\": \"The remote application is in deadlock.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Check that the remote application is operational, by accessing it as usual from the browser.\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"There is a network connection problem.\",\n        \"action\": [\n          {\n            \"id\": 2,\n            \"task\": \"Use tools like ping, telnet or Wire Shark to check the connection to the remote machine. You may want to contact your network administrator.\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"event\": \"connection-refuse\",\n    \"title\":\"The remote application is not responding\",\n    \"summary\": \"The application was attempting to connect to the remote application but the connection was refused.\",\n    \"solution\": [\n      {\n        \"cause\": \"You may have the correct URL but the wrong Port.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Double check an make sure you are using the correct port if a port is required. Review the documentation that describes which ports are required to open.\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"The remote application is down.\",\n        \"action\": [\n          {\n            \"id\": 2,\n            \"task\": \"Check that the remote application is operational, by accessing it from the browser using the application URL (or the display URL if the remote application is behind a reverse proxy).\"\n          },\n          {\n            \"id\": 3,\n            \"task\": \"If the remote application is not accessible with the browser, ping the remote application URL from the local server – the remote application must be accessible using the application URL for the application link to work.\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"The application URL is mis-configured.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Does the application URL use the correct port? If you're using the IP address for the application URL, is that correct?\"\n          },\n          {\n            \"id\": 2,\n            \"task\": \"Does the application URL match the base URL of the remote application (or the display URL if the remote application is behind a reverse proxy )?\"\n          },\n          {\n            \"id\": 3,\n            \"task\": \"Does the application URL use the correct context path?\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"A firewall is blocking access.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Check that the firewall configuration allows access on the required port.\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"event\": \"unknown-host\",\n    \"title\":\"Unable to reach the remote application\",\n    \"summary\": \"The application link was attempting to connect to the remote application but the hostname of the remote application couldn't be resolved.\",\n    \"solution\": [\n      {\n        \"cause\": \"Misconfigured DNS.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Check your DNS configuration, particularly for private networks..\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"The application URL for the remote application is mis-configured, or may have changed recently.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Is the host name correct?\"\n          },\n          {\n            \"id\": 2,\n            \"task\": \"Is the port correct?\"\n          },\n          {\n            \"id\": 3,\n            \"task\": \"Is the context path correct?\"\n          },\n          {\n            \"id\": 4,\n            \"task\": \"Does the application URL match the base URL for the remote application (or the display URL if the remote application is behind a reverse proxy)?\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"event\": \"no-route\",\n    \"title\":\"Unable to locate the remote application\",\n    \"summary\": \"The application link was attempting to connect to the remote application but couldn't even contact it.\",\n    \"solution\": [\n      {\n        \"cause\": \"A firewall is blocking requests.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Check that the firewall configuration allows access on the required port. Use a tool like traceroute to show the path of traffic between the local and remote machines\"\n          }\n        ]\n      },\n      {\n        \"cause\": \"An intermediate router is down.\",\n        \"action\": [\n          {\n            \"id\": 1,\n            \"task\": \"Use a tool like traceroute to show the path of traffic between the local and remote machines.\"\n          }\n        ]\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "src/assets/api/cpu-model.json",
    "content": "[\n  {\n    \"name\": \"CPU 1\",\n    \"series\": [\n      {\n        \"name\": \"used\",\n        \"value\": 75\n      },\n      {\n        \"name\": \"available\",\n        \"value\": 100\n      }\n    ]\n  },\n  {\n    \"name\": \"CPU 2\",\n    \"series\": [\n      {\n        \"name\": \"used\",\n        \"value\": 23\n      },\n      {\n        \"name\": \"available\",\n        \"value\": 77\n      }\n    ]\n  },\n  {\n    \"name\": \"CPU 3\",\n    \"series\": [\n      {\n        \"name\": \"used\",\n        \"value\": 7\n      },\n      {\n        \"name\": \"available\",\n        \"value\": 93\n      }\n    ]\n  }\n]\n\n\n"
  },
  {
    "path": "src/assets/api/disk-help-model.json",
    "content": "{\n  \"heading\": \"Disk Information\",\n  \"summary\": \"\",\n  \"details\": [\n    {\n      \"category\": \"Disk1\",\n      \"articles\": [\n        {\n          \"headline\": \"IOPS\",\n          \"description\": \"ECX enables automated seeding of your SQL Server AlwaysON availability group by leveraging Storage snapshot technology to minimize the data movement between primary and secondary replica.\",\n          \"benefit\": \"Automatically and efficiently initialize AlwaysOn availability group.\",\n          \"id\": \"id string\",\n          \"date\": \"09/10/2017\"\n        }\n      ]\n    },\n    {\n      \"category\": \"Disk2\",\n      \"articles\": [\n        {\n          \"headline\": \"IOPS\",\n          \"description\": \"ECX 2.7 introduces CDM support for SAP HANA 2.0 SPS01. Single tenant configuration can now be automatically protected using storage snapshot.\",\n          \"benefit\": \"Protect your latest version of SAP HANA using ECX Copy Data Management\",\n          \"id\": \"id string\",\n          \"date\": \"09/10/2017\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/assets/api/disk-model.json",
    "content": "[\n  {\n    \"name\": \"used\",\n    \"value\": 45\n  }\n\n]"
  },
  {
    "path": "src/assets/api/donut-model.json",
    "content": "[\n  {\n    \"name\": \"compliant\",\n    \"value\": 6,\n    \"detail\": [\n      {\n        \"id\": \"1234\",\n        \"name\": \"20GA_Exchange\",\n        \"type\": \"vm\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"2345\",\n        \"name\": \"Windows Prod1\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"2346\",\n        \"name\": \"Red Hat test 1\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"2347\",\n        \"name\": \"Centos test 1\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"2348\",\n        \"name\": \"Ubuntu Prod1\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"2349\",\n        \"name\": \"Ubuntu Prod2\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"name\": \"staged\",\n    \"value\": 4,\n    \"detail\": [\n      {\n        \"id\": \"5678\",\n        \"name\": \"20GA_SQL\",\n        \"type\": \"vm\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"9101\",\n        \"name\": \"Windows 2016 Prod1\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"9102\",\n        \"name\": \"Oracle Version a\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"9103\",\n        \"name\": \"Catalog VM Server1\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"name\": \"non-compliant\",\n    \"value\": 2,\n    \"detail\": [\n      {\n        \"id\": \"1213\",\n        \"name\": \"MY SQL\",\n        \"type\": \"vm\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      },\n      {\n        \"id\": \"1415\",\n        \"name\": \"QA System 1\",\n        \"tags\": [\n          {\n            \"facet\": \"Informational\",\n            \"name\": \"storage\"\n          }\n        ]\n      }\n    ]\n  }\n]"
  },
  {
    "path": "src/assets/api/gadget-library-model-prod.json",
    "content": "{\n  \"library\": [\n    {\n      \"componentType\": \"PortConnectionGadgetComponent\",\n      \"name\": \"Port Connection Test\",\n      \"description\": \"Test Connection To Endpoints.\",\n      \"icon\": \"assets/images/response.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Informational\",\n          \"name\": \"port-connection\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Connection Test\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"host\",\n                \"label\": \"Host\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dropdown\",\n                \"key\": \"port\",\n                \"label\": \"Port(s)\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3,\n                \"options\": [\n                  {\n                    \"key\": \"vSnap + vAdp (All Ports)\",\n                    \"value\": \"8900,8098,8080,22,111,20048,2049\"\n                  },\n                  {\n                    \"key\": \"SPP Single Appliance (All Ports)\",\n                    \"value\": \"443,8900,22,111,20048,2049\"\n                  },\n                  {\n                    \"key\": \"SPP (443)\",\n                    \"value\": \"443\"\n                  },\n                  {\n                    \"key\": \"SPP (8443)\",\n                    \"value\": \"8443\"\n                  },\n                  {\n                    \"key\": \"SPP (3000)\",\n                    \"value\": \"3000\"\n                  },\n                  {\n                    \"key\": \"LDAP (389)\",\n                    \"value\": \"389\"\n                  },\n                  {\n                    \"key\": \"LDAP (636)\",\n                    \"value\": \"636\"\n                  },\n                  {\n                    \"key\": \"VADP (8080)\",\n                    \"value\": \"8080\"\n                  },\n \t\t  {\n                    \"key\": \"VADP on vSnap (8098)\",\n                    \"value\": \"8098\"\n                  },\n                  {\n                    \"key\": \"WinRM (5985)\",\n                    \"value\": \"5985\"\n                  },\n                  {\n                    \"key\": \"VSnap (8900)\",\n                    \"value\": \"8900\"\n                  },\n                  {\n                    \"key\": \"SSH (22)\",\n                    \"value\": \"22\"\n                  },\n                  {\n                    \"key\": \"ISCSI (3260)\",\n                    \"value\": \"3260\"\n                  },\n                  {\n                    \"key\": \"NFS (2049)\",\n                    \"value\": \"2049\"\n                  },\n                  {\n                    \"key\": \"NFS (20048)\",\n                    \"value\": \"20048\"\n                  },\n                  {\n                    \"key\": \"NFS (111)\",\n                    \"value\": \"111\"\n                  },\n                  {\n                    \"key\": \"ESXI (902)\",\n                    \"value\": \"902\"\n                  }\n                ]\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"BarChartGadgetComponent\",\n      \"name\": \"Bar Chart\",\n      \"description\": \"Bar Char\",\n      \"icon\": \"assets/images/cpu.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"metric\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"bar\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Bar Chart Data\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"state\",\n                \"label\": \"\",\n                \"value\": \"stop\",\n                \"required\": true,\n                \"order\": -1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -2\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"dropdown\",\n                \"type\": \"dropdown\",\n                \"key\": \"barChartType\",\n                \"label\": \"Bar Chart Type\",\n                \"value\": \"normalizedHorizontal\",\n                \"required\": true,\n                \"order\": 1,\n                \"options\": [\n                  {\n                    \"key\": \"Normalized Horizontal\",\n                    \"value\": \"normalizedHorizontal\"\n                  },\n                  {\n                    \"key\": \"Normalized Vertical\",\n                    \"value\": \"normalizedVertical\"\n                  },\n                  {\n                    \"key\": \"Stacked Horizontal\",\n                    \"value\": \"stackedHorizontal\"\n                  },\n                  {\n                    \"key\": \"Stacked Vertical\",\n                    \"value\": \"stackedVertical\"\n                  }\n                ]\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"yAxisLabel\",\n                \"label\": \"Y Axis Label\",\n                \"value\": \"\",\n                \"required\": false,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"xAxisLabel\",\n                \"label\": \"X Axis Label\",\n                \"value\": \"\",\n                \"required\": false,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"gradient\",\n                \"label\": \"Show colors in gradient\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showDataLabel\",\n                \"label\": \"Show data label\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 5\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showXAxis\",\n                \"label\": \"Show x axis\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 6\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showYAxis\",\n                \"label\": \"Show y axis\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 7\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showLegend\",\n                \"label\": \"Show chart legend\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 8\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showXAxisLabel\",\n                \"label\": \"Show x axis label\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 9\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showYAxisLabel\",\n                \"label\": \"Show y axis label\",\n                \"value\": false,\n                \"required\": false,\n                \"order\": 10\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"PieChartGadgetComponent\",\n      \"name\": \"Pie Chart\",\n      \"description\": \"Pie Chart\",\n      \"icon\": \"assets/images/pie.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"metric\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"pie\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Pie Chart\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"state\",\n                \"label\": \"\",\n                \"value\": \"stop\",\n                \"required\": true,\n                \"order\": -2\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"explodeSlices\",\n                \"label\": \"Explode slices\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 1\n              },{\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showDonut\",\n                \"label\": \"Show donut\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"gradient\",\n                \"label\": \"Show colors in gradient\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showLegend\",\n                \"label\": \"Show chart legend\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showLabels\",\n                \"label\": \"Show labels\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 5\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    }\n  ]\n}\n\n"
  },
  {
    "path": "src/assets/api/gadget-library-model.json",
    "content": "{\n  \"library\": [\n    {\n      \"componentType\": \"BarChartGadgetComponent\",\n      \"name\": \"Bar Chart\",\n      \"description\": \"Bar Char\",\n      \"icon\": \"assets/images/cpu.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"metric\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"bar\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Bar Chart Data\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"state\",\n                \"label\": \"\",\n                \"value\": \"stop\",\n                \"required\": true,\n                \"order\": -1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -2\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"dropdown\",\n                \"type\": \"dropdown\",\n                \"key\": \"barChartType\",\n                \"label\": \"Bar Chart Type\",\n                \"value\": \"normalizedHorizontal\",\n                \"required\": true,\n                \"order\": 1,\n                \"options\": [\n                  {\n                    \"key\": \"Normalized Horizontal\",\n                    \"value\": \"normalizedHorizontal\"\n                  },\n                  {\n                    \"key\": \"Normalized Vertical\",\n                    \"value\": \"normalizedVertical\"\n                  },\n                  {\n                    \"key\": \"Stacked Horizontal\",\n                    \"value\": \"stackedHorizontal\"\n                  },\n                  {\n                    \"key\": \"Stacked Vertical\",\n                    \"value\": \"stackedVertical\"\n                  }\n                ]\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"yAxisLabel\",\n                \"label\": \"Y Axis Label\",\n                \"value\": \"\",\n                \"required\": false,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"xAxisLabel\",\n                \"label\": \"X Axis Label\",\n                \"value\": \"\",\n                \"required\": false,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"gradient\",\n                \"label\": \"Show colors in gradient\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showDataLabel\",\n                \"label\": \"Show data label\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 5\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showXAxis\",\n                \"label\": \"Show x axis\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 6\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showYAxis\",\n                \"label\": \"Show y axis\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 7\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showLegend\",\n                \"label\": \"Show chart legend\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 8\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showXAxisLabel\",\n                \"label\": \"Show x axis label\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 9\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showYAxisLabel\",\n                \"label\": \"Show y axis label\",\n                \"value\": false,\n                \"required\": false,\n                \"order\": 10\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"PieChartGadgetComponent\",\n      \"name\": \"Pie Chart\",\n      \"description\": \"Pie Chart\",\n      \"icon\": \"assets/images/pie.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"metric\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"pie\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Pie Chart\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"state\",\n                \"label\": \"\",\n                \"value\": \"stop\",\n                \"required\": true,\n                \"order\": -2\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"explodeSlices\",\n                \"label\": \"Explode slices\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showDonut\",\n                \"label\": \"Show donut\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"gradient\",\n                \"label\": \"Show colors in gradient\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showLegend\",\n                \"label\": \"Show chart legend\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showLabels\",\n                \"label\": \"Show labels\",\n                \"value\": true,\n                \"required\": false,\n                \"order\": 5\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"BubbleGadgetComponent\",\n      \"name\": \"Bubble\",\n      \"description\": \"Bubble Gadget\",\n      \"icon\": \"assets/images/bubble.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Bubble\",\n          \"name\": \"bubble\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Bubble\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": false,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"StorageObjectListComponent\",\n      \"name\": \"Storage Information\",\n      \"description\": \"Provides a storage view.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Informational\",\n          \"name\": \"storage\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Data Source\",\n                \"value\": \"vSnap\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Storage - Volume Analysis\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"CPUMGadgetComponent\",\n      \"name\": \"CPUM Chart\",\n      \"description\": \"Monitors CPU utilization.\",\n      \"icon\": \"assets/images/cpu.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Performance\",\n          \"name\": \"real-time\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"bar\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"EXP CPU Monitor utilization\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Threshold\",\n            \"groupId\": \"alert\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"number\",\n                \"key\": \"cpuErrorThreshold\",\n                \"label\": \"Utilization Error Threshold (%)\",\n                \"value\": 90,\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"number\",\n                \"key\": \"cpuWarningThreshold\",\n                \"label\": \"Utilization Warning Threshold (%)\",\n                \"value\": 75,\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"number\",\n                \"key\": \"cpuThresholdTime\",\n                \"label\": \"Maximum Exceed Threshold Time (minutes)\",\n                \"value\": 10,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"type\": \"textbox\",\n                \"key\": \"orientation\",\n                \"label\": \"Orientation\",\n                \"value\": \"horizontal\",\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"xAxis\",\n                \"label\": \"Show X Axis\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"yAxis\",\n                \"label\": \"Show Y Axis\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"legend\",\n                \"label\": \"Show Legend\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 5\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"gradient\",\n                \"label\": \"Use Gradient\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 6\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showGridLines\",\n                \"label\": \"Show Grid Lines\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 7\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showXAxisLabel\",\n                \"label\": \"Show X Axis Label\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 8\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"showYAxisLabel\",\n                \"label\": \"Show Y Axis Label\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 9\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"PortConnectionGadgetComponent\",\n      \"name\": \"Port Connection Test\",\n      \"description\": \"Test Connection To Endpoints.\",\n      \"icon\": \"assets/images/response.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Informational\",\n          \"name\": \"port-connection\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Connection Test\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"host\",\n                \"label\": \"Host\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dropdown\",\n                \"key\": \"port\",\n                \"label\": \"Port(s)\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3,\n                \"options\": [\n                  {\n                    \"key\": \"vSnap + vAdp (All Ports)\",\n                    \"value\": \"8900,8098, 8080,22,111,20048,2049\"\n                  },\n                  {\n                    \"key\": \"SPP Single Appliance (All Ports)\",\n                    \"value\": \"443,8900,22,111,20048,2049\"\n                  },\n                  {\n                    \"key\": \"SPP (443)\",\n                    \"value\": \"443\"\n                  },\n                  {\n                    \"key\": \"SPP (8443)\",\n                    \"value\": \"8443\"\n                  },\n                  {\n                    \"key\": \"SPP (3000)\",\n                    \"value\": \"3000\"\n                  },\n                  {\n                    \"key\": \"LDAP (389)\",\n                    \"value\": \"389\"\n                  },\n                  {\n                    \"key\": \"LDAP (636)\",\n                    \"value\": \"636\"\n                  },\n                  {\n                    \"key\": \"VADP (8080)\",\n                    \"value\": \"8080\"\n                  },\n\t\t  {\n                    \"key\": \"VADP on vSnap (8098)\",\n                    \"value\": \"8098\"\n                  },\n                  {\n                    \"key\": \"WinRM (5985)\",\n                    \"value\": \"5985\"\n                  },\n                  {\n                    \"key\": \"VSnap (8900)\",\n                    \"value\": \"8900\"\n                  },\n                  {\n                    \"key\": \"SSH (22)\",\n                    \"value\": \"22\"\n                  },\n                  {\n                    \"key\": \"ISCSI (3260)\",\n                    \"value\": \"3260\"\n                  },\n                  {\n                    \"key\": \"NFS (2049)\",\n                    \"value\": \"2049\"\n                  },\n                  {\n                    \"key\": \"NFS (20048)\",\n                    \"value\": \"20048\"\n                  },\n                  {\n                    \"key\": \"NFS (111)\",\n                    \"value\": \"111\"\n                  },\n                  {\n                    \"key\": \"ESXI (902)\",\n                    \"value\": \"902\"\n                  }\n                ]\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"EdgeServiceListGadgetComponent\",\n      \"name\": \"Edge Service Status\",\n      \"description\": \"Monitors edge service status\",\n      \"icon\": \"assets/images/edge-service.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"List\",\n          \"name\": \"health\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"Carlosappliance\",\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Proxy service status\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"List\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"TrendGadgetComponent\",\n      \"name\": \"Trend\",\n      \"description\": \"General trends.\",\n      \"icon\": \"assets/images/trend.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Performance\",\n          \"name\": \"trend\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"area\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Trend\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"TrendLineGadgetComponent\",\n      \"name\": \"Realtime Performance\",\n      \"description\": \"Monitors IOPs and network bandwidth.\",\n      \"icon\": \"assets/images/trend-line.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Performance\",\n          \"name\": \"trend\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"line\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Performance\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"CPUGadgetComponent\",\n      \"name\": \"CPU Chart\",\n      \"description\": \"Monitors CPU utilization.\",\n      \"icon\": \"assets/images/cpu.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Performance\",\n          \"name\": \"real-time\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"bar\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"CPU utilization\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"MemoryGadgetComponent\",\n      \"name\": \"Memory Chart\",\n      \"description\": \"Monitors memory utilization\",\n      \"icon\": \"assets/images/memory.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Performance\",\n          \"name\": \"real-time\"\n        },\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"gauge\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Memory Utilization\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"ServiceListGadgetComponent\",\n      \"name\": \"Service Status\",\n      \"description\": \"Monitors service status\",\n      \"icon\": \"assets/images/service.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"List\",\n          \"name\": \"health\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 2\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Service Status\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"List\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"PropertyListGadgetComponent\",\n      \"name\": \"Tuning Parameters\",\n      \"description\": \"System related tuning parameters.\",\n      \"icon\": \"assets/images/property.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"List\",\n          \"name\": \"tuning\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Tuning\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 999,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"CPU Utilization\",\n                \"required\": true,\n                \"order\": 1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"DiskGadgetComponent\",\n      \"name\": \"Disk Utilization\",\n      \"description\": \"Disk consumption information.\",\n      \"icon\": \"assets/images/donut.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"pie\"\n        },\n        {\n          \"facet\": \"Performance\",\n          \"name\": \"storage\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Disk Consumption\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"number\",\n                \"key\": \"threshold\",\n                \"label\": \"Consumed Threshold\",\n                \"value\": 50,\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"dropdown\",\n                \"key\": \"diskid\",\n                \"label\": \"Disk Id\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 2,\n                \"options\": [\n                  {\n                    \"key\": \"2344112gdfgdfg\",\n                    \"value\": \"2344112gdfgdfg\"\n                  },\n                  {\n                    \"key\": \"g3g3egegre\",\n                    \"value\": \"g3g3egegre\"\n                  },\n                  {\n                    \"key\": \"8435f34\",\n                    \"value\": \"8435f34\"\n                  }\n                ]\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Thresholds\",\n            \"groupId\": \"threshold\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"number\",\n                \"key\": \"frequency\",\n                \"label\": \"Frequency\",\n                \"value\": 30,\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"number\",\n                \"key\": \"retentionH\",\n                \"label\": \"Retention High\",\n                \"value\": 30,\n                \"required\": true,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"number\",\n                \"key\": \"retentionL\",\n                \"label\": \"Retention Low\",\n                \"value\": 180,\n                \"required\": true,\n                \"order\": 4\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"DonutGadgetComponent\",\n      \"name\": \"Smart Protection\",\n      \"description\": \"Ai based protection.\",\n      \"icon\": \"assets/images/smart-protect.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Chart\",\n          \"name\": \"pie\"\n        },\n        {\n          \"facet\": \"Performance\",\n          \"name\": \"storage\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 4\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Smart Protection\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"number\",\n                \"key\": \"frequency\",\n                \"label\": \"Compliant Check Frequency\",\n                \"value\": 50,\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"auto\",\n                \"label\": \"Use AI to automate compliance\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          },\n          {\n            \"displayName\": \"Chart\",\n            \"groupId\": \"chart\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"checkbox\",\n                \"type\": \"checkbox\",\n                \"key\": \"chart_properties\",\n                \"label\": \"Show chart details\",\n                \"value\": true,\n                \"required\": true,\n                \"order\": 3\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"StatisticGadgetComponent\",\n      \"name\": \"Statistic\",\n      \"description\": \"General statistic.\",\n      \"icon\": \"assets/images/statistic.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Statistic\",\n          \"name\": \"counter\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dropdown\",\n                \"key\": \"resource\",\n                \"label\": \"Resource\",\n                \"value\": \"vm\",\n                \"required\": true,\n                \"order\": 2,\n                \"options\": [\n                  {\n                    \"key\": \"vm\",\n                    \"value\": \"vm\"\n                  },\n                  {\n                    \"key\": \"database\",\n                    \"value\": \"database\"\n                  },\n                  {\n                    \"key\": \"volume\",\n                    \"value\": \"volume\"\n                  },\n                  {\n                    \"key\": \"job\",\n                    \"value\": \"job\"\n                  }\n                ]\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Statistic\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": false,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"NewsGadgetComponent\",\n      \"name\": \"News\",\n      \"description\": \"What's new\",\n      \"icon\": \"assets/images/news.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Informational\",\n          \"name\": \"news\"\n        },\n        {\n          \"facet\": \"List\",\n          \"name\": \"news\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"News URL\",\n                \"value\": \"news\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"News\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"JobAnalysisGadgetComponent\",\n      \"name\": \"Job Analyzer\",\n      \"description\": \"Performs operation analysis.\",\n      \"icon\": \"assets/images/job-analysis.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Informational\",\n          \"name\": \"job\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 10,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Application URL\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Device URL\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Job Anaylyzer\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": true,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    },\n    {\n      \"componentType\": \"TodoGadgetComponent\",\n      \"name\": \"Todo\",\n      \"description\": \"Todo Gadget\",\n      \"icon\": \"assets/images/todo.png\",\n      \"instanceId\": -1,\n      \"tags\": [\n        {\n          \"facet\": \"Todo\",\n          \"name\": \"todo\"\n        }\n      ],\n      \"config\": {\n        \"propertyPages\": [\n          {\n            \"displayName\": \"Run\",\n            \"groupId\": \"run\",\n            \"position\": 11,\n            \"properties\": [\n              {\n                \"controlType\": \"dynamicdropdown\",\n                \"key\": \"endpoint\",\n                \"label\": \"Chart Data Source\",\n                \"value\": \"\",\n                \"required\": true,\n                \"order\": 3\n              },\n              {\n                \"controlType\": \"textbox\",\n                \"key\": \"title\",\n                \"label\": \"Title\",\n                \"value\": \"Todo\",\n                \"required\": true,\n                \"order\": 1\n              },\n              {\n                \"controlType\": \"hidden\",\n                \"key\": \"instanceId\",\n                \"label\": \"\",\n                \"value\": 2,\n                \"required\": false,\n                \"order\": -1\n              }\n            ]\n          }\n        ]\n      },\n      \"actions\": [\n        {\n          \"name\": \"Add\"\n        }\n      ]\n    }\n  ]\n}\n\n"
  },
  {
    "path": "src/assets/api/http-codes.json",
    "content": "[\n  {\n    \"code\": \"1xx\",\n    \"phrase\": \"**Informational**\",\n    \"description\": \"\\\"indicates an interim response for communicating connection status or request progress prior to completing the requested action and sending a final response.\\\" ~ [sure](http://www.urbandictionary.com/define.php?term=sure)\",\n    \"spec_title\": \"RFC7231#6.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.2\"\n  },\n  {\n    \"code\": \"100\",\n    \"phrase\": \"Continue\",\n    \"description\": \"\\\"indicates that the initial part of a request has been received and has not yet been rejected by the server.\\\"\",\n    \"spec_title\": \"RFC7231#6.2.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.2.1\"\n  },\n  {\n    \"code\": \"101\",\n    \"phrase\": \"Switching Protocols\",\n    \"description\": \"\\\"indicates that the server understands and is willing to comply with the client's request, via the Upgrade header field, for a change in the application protocol being used on this connection.\\\"\",\n    \"spec_title\": \"RFC7231#6.2.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.2.2\"\n  },\n  {\n    \"code\": \"2xx\",\n    \"phrase\": \"**Successful**\",\n    \"description\": \"\\\"indicates that the client's request was successfully received, understood, and accepted.\\\" ~ [cool](https://twitter.com/DanaDanger/status/183316183494311936)\",\n    \"spec_title\": \"RFC7231#6.3\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.3\"\n  },\n  {\n    \"code\": \"200\",\n    \"phrase\": \"OK\",\n    \"description\": \"\\\"indicates that the request has succeeded.\\\"\",\n    \"spec_title\": \"RFC7231#6.3.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.3.1\"\n  },\n  {\n    \"code\": \"201\",\n    \"phrase\": \"Created\",\n    \"description\": \"\\\"indicates that the request has been fulfilled and has resulted in one or more new resources being created.\\\"\",\n    \"spec_title\": \"RFC7231#6.3.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.3.2\"\n  },\n  {\n    \"code\": \"202\",\n    \"phrase\": \"Accepted\",\n    \"description\": \"\\\"indicates that the request has been accepted for processing, but the processing has not been completed.\\\"\",\n    \"spec_title\": \"RFC7231#6.3.3\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.3.3\"\n  },\n  {\n    \"code\": \"203\",\n    \"phrase\": \"Non-Authoritative Information\",\n    \"description\": \"\\\"indicates that the request was successful but the enclosed payload has been modified from that of the origin server's 200 (OK) response by a transforming proxy.\\\"\",\n    \"spec_title\": \"RFC7231#6.3.4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.3.4\"\n  },\n  {\n    \"code\": \"204\",\n    \"phrase\": \"No Content\",\n    \"description\": \"\\\"indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body.\\\"\",\n    \"spec_title\": \"RFC7231#6.3.5\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.3.5\"\n  },\n  {\n    \"code\": \"205\",\n    \"phrase\": \"Reset Content\",\n    \"description\": \"\\\"indicates that the server has fulfilled the request and desires that the user agent reset the \\\"document view\\\", which caused the request to be sent, to its original state as received from the origin server.\\\"\",\n    \"spec_title\": \"RFC7231#6.3.6\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.3.6\"\n  },\n  {\n    \"code\": \"206\",\n    \"phrase\": \"Partial Content\",\n    \"description\": \"\\\"indicates that the server is successfully fulfilling a range request for the target resource by transferring one or more parts of the selected representation that correspond to the satisfiable ranges found in the requests's Range header field.\\\"\",\n    \"spec_title\": \"RFC7233#4.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7233#section-4.1\"\n  },\n  {\n    \"code\": \"3xx\",\n    \"phrase\": \"**Redirection**\",\n    \"description\": \"\\\"indicates that further action needs to be taken by the user agent in order to fulfill the request.\\\" ~ [ask that dude over there](https://twitter.com/DanaDanger/status/183316183494311936)\",\n    \"spec_title\": \"RFC7231#6.4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.4\"\n  },\n  {\n    \"code\": \"300\",\n    \"phrase\": \"Multiple Choices\",\n    \"description\": \"\\\"indicates that the target resource has more than one representation, each with its own more specific identifier, and information about the alternatives is being provided so that the user (or user agent) can select a preferred representation by redirecting its request to one or more of those identifiers.\\\"\",\n    \"spec_title\": \"RFC7231#6.4.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.4.1\"\n  },\n  {\n    \"code\": \"301\",\n    \"phrase\": \"Moved Permanently\",\n    \"description\": \"\\\"indicates that the target resource has been assigned a new permanent URI and any future references to this resource ought to use one of the enclosed URIs.\\\"\",\n    \"spec_title\": \"RFC7231#6.4.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.4.2\"\n  },\n  {\n    \"code\": \"302\",\n    \"phrase\": \"Found\",\n    \"description\": \"\\\"indicates that the target resource resides temporarily under a different URI.\\\"\",\n    \"spec_title\": \"RFC7231#6.4.3\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.4.3\"\n  },\n  {\n    \"code\": \"303\",\n    \"phrase\": \"See Other\",\n    \"description\": \"\\\"indicates that the server is redirecting the user agent to a different resource, as indicated by a URI in the Location header field, that is intended to provide an indirect response to the original request.\\\"\",\n    \"spec_title\": \"RFC7231#6.4.4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.4.4\"\n  },\n  {\n    \"code\": \"304\",\n    \"phrase\": \"Not Modified\",\n    \"description\": \"\\\"indicates that a conditional GET request has been received and would have resulted in a 200 (OK) response if it were not for the fact that the condition has evaluated to false.\\\"\",\n    \"spec_title\": \"RFC7232#4.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7232#section-4.1\"\n  },\n  {\n    \"code\": \"305\",\n    \"phrase\": \"Use Proxy\",\n    \"description\": \"*deprecated*\",\n    \"spec_title\": \"RFC7231#6.4.5\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.4.5\"\n  },\n  {\n    \"code\": \"307\",\n    \"phrase\": \"Temporary Redirect\",\n    \"description\": \"\\\"indicates that the target resource resides temporarily under a different URI and the user agent MUST NOT change the request method if it performs an automatic redirection to that URI.\\\"\",\n    \"spec_title\": \"RFC7231#6.4.7\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.4.7\"\n  },\n  {\n    \"code\": \"4xx\",\n    \"phrase\": \"**Client Error**\",\n    \"description\": \"\\\"indicates that the client seems to have erred.\\\" ~ [*you* fucked up](https://twitter.com/DanaDanger/status/183316183494311936)\",\n    \"spec_title\": \"RFC7231#6.5\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5\"\n  },\n  {\n    \"code\": \"400\",\n    \"phrase\": \"Bad Request\",\n    \"description\": \"\\\"indicates that the server cannot or will not process the request because the received syntax is invalid, nonsensical, or exceeds some limitation on what the server is willing to process.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.1\"\n  },\n  {\n    \"code\": \"401\",\n    \"phrase\": \"Unauthorized\",\n    \"description\": \"\\\"indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.\\\"\",\n    \"spec_title\": \"RFC7235#6.3.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7235#section-3.1\"\n  },\n  {\n    \"code\": \"402\",\n    \"phrase\": \"Payment Required\",\n    \"description\": \"*reserved*\",\n    \"spec_title\": \"RFC7231#6.5.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.2\"\n  },\n  {\n    \"code\": \"403\",\n    \"phrase\": \"Forbidden\",\n    \"description\": \"\\\"indicates that the server understood the request but refuses to authorize it.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.3\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.3\"\n  },\n  {\n    \"code\": \"404\",\n    \"phrase\": \"Not Found\",\n    \"description\": \"\\\"indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.4\"\n  },\n  {\n    \"code\": \"405\",\n    \"phrase\": \"Method Not Allowed\",\n    \"description\": \"\\\"indicates that the method specified in the request-line is known by the origin server but not supported by the target resource.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.5\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.5\"\n  },\n  {\n    \"code\": \"406\",\n    \"phrase\": \"Not Acceptable\",\n    \"description\": \"\\\"indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request, and the server is unwilling to supply a default representation.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.6\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.6\"\n  },\n  {\n    \"code\": \"407\",\n    \"phrase\": \"Proxy Authentication Required\",\n    \"description\": \"\\\"is similar to 401 (Unauthorized), but indicates that the client needs to authenticate itself in order to use a proxy.\\\"\",\n    \"spec_title\": \"RFC7235#3.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7235#section-3.2\"\n  },\n  {\n    \"code\": \"408\",\n    \"phrase\": \"Request Timeout\",\n    \"description\": \"\\\"indicates that the server did not receive a complete request message within the time that it was prepared to wait.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.7\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.7\"\n  },\n  {\n    \"code\": \"409\",\n    \"phrase\": \"Conflict\",\n    \"description\": \"\\\"indicates that the request could not be completed due to a conflict with the current state of the resource.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.8\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.8\"\n  },\n  {\n    \"code\": \"410\",\n    \"phrase\": \"Gone\",\n    \"description\": \"\\\"indicates that access to the target resource is no longer available at the origin server and that this condition is likely to be permanent.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.9\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.9\"\n  },\n  {\n    \"code\": \"411\",\n    \"phrase\": \"Length Required\",\n    \"description\": \"\\\"indicates that the server refuses to accept the request without a defined Content-Length.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.10\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.10\"\n  },\n  {\n    \"code\": \"412\",\n    \"phrase\": \"Precondition Failed\",\n    \"description\": \"\\\"indicates that one or more preconditions given in the request header fields evaluated to false when tested on the server.\\\"\",\n    \"spec_title\": \"RFC7232#4.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7232#section-4.2\"\n  },\n  {\n    \"code\": \"413\",\n    \"phrase\": \"Payload Too Large\",\n    \"description\": \"\\\"indicates that the server is refusing to process a request because the request payload is larger than the server is willing or able to process.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.11\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.11\"\n  },\n  {\n    \"code\": \"414\",\n    \"phrase\": \"URI Too Long\",\n    \"description\": \"\\\"indicates that the server is refusing to service the request because the request-target is longer than the server is willing to interpret.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.12\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.12\"\n  },\n  {\n    \"code\": \"415\",\n    \"phrase\": \"Unsupported Media Type\",\n    \"description\": \"\\\"indicates that the origin server is refusing to service the request because the payload is in a format not supported by the target resource for this method.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.13\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.13\"\n  },\n  {\n    \"code\": \"416\",\n    \"phrase\": \"Range Not Satisfiable\",\n    \"description\": \"\\\"indicates that none of the ranges in the request's Range header field overlap the current extent of the selected resource or that the set of ranges requested has been rejected due to invalid ranges or an excessive request of small or overlapping ranges.\\\"\",\n    \"spec_title\": \"RFC7233#4.4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7233#section-4.4\"\n  },\n  {\n    \"code\": \"417\",\n    \"phrase\": \"Expectation Failed\",\n    \"description\": \"\\\"indicates that the expectation given in the request's Expect header field could not be met by at least one of the inbound servers.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.14\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.14\"\n  },\n  {\n    \"code\": \"418\",\n    \"phrase\": \"I'm a teapot\",\n    \"description\": \"\\\"Any attempt to brew coffee with a teapot should result in the error code 418 I'm a teapot.\\\"\",\n    \"spec_title\": \"RFC2324#2.3.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2324#section-2.3.1\"\n  },\n  {\n    \"code\": \"426\",\n    \"phrase\": \"Upgrade Required\",\n    \"description\": \"\\\"indicates that the server refuses to perform the request using the current protocol but might be willing to do so after the client upgrades to a different protocol.\\\"\",\n    \"spec_title\": \"RFC7231#6.5.15\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.5.15\"\n  },\n  {\n    \"code\": \"5xx\",\n    \"phrase\": \"**Server Error**\",\n    \"description\": \"\\\"indicates that the server is aware that it has erred or is incapable of performing the requested method.\\\" ~ [*we* fucked up](https://twitter.com/DanaDanger/status/183316183494311936)\",\n    \"spec_title\": \"RFC7231#6.6\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.6\"\n  },\n  {\n    \"code\": \"500\",\n    \"phrase\": \"Internal Server Error\",\n    \"description\": \"\\\"indicates that the server encountered an unexpected condition that prevented it from fulfilling the request.\\\"\",\n    \"spec_title\": \"RFC7231#6.6.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.6.1\"\n  },\n  {\n    \"code\": \"501\",\n    \"phrase\": \"Not Implemented\",\n    \"description\": \"\\\"indicates that the server does not support the functionality required to fulfill the request.\\\"\",\n    \"spec_title\": \"RFC7231#6.6.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.6.2\"\n  },\n  {\n    \"code\": \"502\",\n    \"phrase\": \"Bad Gateway\",\n    \"description\": \"\\\"indicates that the server, while acting as a gateway or proxy, received an invalid response from an inbound server it accessed while attempting to fulfill the request.\\\"\",\n    \"spec_title\": \"RFC7231#6.6.3\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.6.3\"\n  },\n  {\n    \"code\": \"503\",\n    \"phrase\": \"Service Unavailable\",\n    \"description\": \"\\\"indicates that the server is currently unable to handle the request due to a temporary overload or scheduled maintenance, which will likely be alleviated after some delay.\\\"\",\n    \"spec_title\": \"RFC7231#6.6.4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.6.4\"\n  },\n  {\n    \"code\": \"504\",\n    \"phrase\": \"Gateway Time-out\",\n    \"description\": \"\\\"indicates that the server, while acting as a gateway or proxy, did not receive a timely response from an upstream server it needed to access in order to complete the request.\\\"\",\n    \"spec_title\": \"RFC7231#6.6.5\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.6.5\"\n  },\n  {\n    \"code\": \"505\",\n    \"phrase\": \"HTTP Version Not Supported\",\n    \"description\": \"\\\"indicates that the server does not support, or refuses to support, the protocol version that was used in the request message.\\\"\",\n    \"spec_title\": \"RFC7231#6.6.6\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7231#section-6.6.6\"\n  },\n  {\n    \"code\": \"102\",\n    \"phrase\": \"Processing\",\n    \"description\": \"\\\"is an interim response used to inform the client that the server has accepted the complete request, but has not yet completed it.\\\"\",\n    \"spec_title\": \"RFC5218#10.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2518#section-10.1\"\n  },\n  {\n    \"code\": \"207\",\n    \"phrase\": \"Multi-Status\",\n    \"description\": \"\\\"provides status for multiple independent operations.\\\"\",\n    \"spec_title\": \"RFC5218#10.2\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2518#section-10.2\"\n  },\n  {\n    \"code\": \"226\",\n    \"phrase\": \"IM Used\",\n    \"description\": \"\\\"The server has fulfilled a GET request for the resource, and the response is a representation of the result of one or more instance-manipulations applied to the current instance.\\\"\",\n    \"spec_title\": \"RFC3229#10.4.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc3229#section-10.4.1\"\n  },\n  {\n    \"code\": \"308\",\n    \"phrase\": \"Permanent Redirect\",\n    \"description\": \"\\\"The target resource has been assigned a new permanent URI and any future references to this resource outght to use one of the enclosed URIs. [...] This status code is similar to 301 Moved Permanently (Section 7.3.2 of rfc7231), except that it does not allow rewriting the request method from POST to GET.\\\"\",\n    \"spec_title\": \"RFC7538\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc7538\"\n  },\n  {\n    \"code\": \"422\",\n    \"phrase\": \"Unprocessable Entity\",\n    \"description\": \"\\\"means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions.\\\"\",\n    \"spec_title\": \"RFC5218#10.3\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2518#section-10.3\"\n  },\n  {\n    \"code\": \"423\",\n    \"phrase\": \"Locked\",\n    \"description\": \"\\\"means the source or destination resource of a method is locked.\\\"\",\n    \"spec_title\": \"RFC5218#10.4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2518#section-10.4\"\n  },\n  {\n    \"code\": \"424\",\n    \"phrase\": \"Failed Dependency\",\n    \"description\": \"\\\"means that the method could not be performed on the resource because the requested action depended on another action and that action failed.\\\"\",\n    \"spec_title\": \"RFC5218#10.5\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2518#section-10.5\"\n  },\n  {\n    \"code\": \"428\",\n    \"phrase\": \"Precondition Required\",\n    \"description\": \"\\\"indicates that the origin server requires the request to be conditional.\\\"\",\n    \"spec_title\": \"RFC6585#3\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc6585#section-3\"\n  },\n  {\n    \"code\": \"429\",\n    \"phrase\": \"Too Many Requests\",\n    \"description\": \"\\\"indicates that the user has sent too many requests in a given amount of time (\\\"rate limiting\\\").\\\"\",\n    \"spec_title\": \"RFC6585#4\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc6585#section-4\"\n  },\n  {\n    \"code\": \"431\",\n    \"phrase\": \"Request Header Fields Too Large\",\n    \"description\": \"\\\"indicates that the server is unwilling to process the request because its header fields are too large.\\\"\",\n    \"spec_title\": \"RFC6585#5\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc6585#section-5\"\n  },\n  {\n    \"code\": \"451\",\n    \"phrase\": \"Unavailable For Legal Reasons\",\n    \"description\": \"\\\"This status code indicates that the server is denying access to the resource in response to a legal demand.\\\"\",\n    \"spec_title\": \"draft-ietf-httpbis-legally-restricted-status\",\n    \"spec_href\": \"https://tools.ietf.org/html/draft-ietf-httpbis-legally-restricted-status\"\n  },\n  {\n    \"code\": \"506\",\n    \"phrase\": \"Variant Also Negotiates\",\n    \"description\": \"\\\"indicates that the server has an internal configuration error: the chosen variant resource is configured to engage in transparent content negotiation itself, and is therefore not a proper end point in the negotiation process.\\\"\",\n    \"spec_title\": \"RFC2295#8.1\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2295#section-8.1\"\n  },\n  {\n    \"code\": \"507\",\n    \"phrase\": \"Insufficient Storage\",\n    \"description\": \"\\\"means the method could not be performed on the resource because the server is unable to store the representation needed to successfully complete the request.\\\"\",\n    \"spec_title\": \"RFC5218#10.6\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc2518#section-10.6\"\n  },\n  {\n    \"code\": \"511\",\n    \"phrase\": \"Network Authentication Required\",\n    \"description\": \"\\\"indicates that the client needs to authenticate to gain network access.\\\"\",\n    \"spec_title\": \"RFC6585#6\",\n    \"spec_href\": \"https://tools.ietf.org/html/rfc6585#section-6\"\n  },\n  {\n    \"code\": \"7xx\",\n    \"phrase\": \"**Developer Error**\",\n    \"description\": \"[err](http://www.urbandictionary.com/define.php?term=err)\",\n    \"spec_title\": \"7xx-rfc\",\n    \"spec_href\": \"http://documentup.com/joho/7XX-rfc\"\n  }\n]"
  },
  {
    "path": "src/assets/api/news-model.json",
    "content": "[\n  {\n    \"heading\": \"\",\n    \"summary\": \"\",\n    \"details\": [\n      {\n        \"category\": \"Application A Enhancements\",\n        \"articles\": [\n          {\n            \"headline\": \"Automated Seeding for Always On\",\n            \"description\": \"Enables automated seeding of your Application A AlwaysON availability group by leveraging Storage snapshot technology to minimize the data movement between primary and secondary replica.\",\n            \"benefit\": \"Automatically and efficiently initialize AlwaysOn availability group.\",\n            \"id\": \"id string\",\n            \"date\": \"09/10/2017\"\n          }\n        ]\n      },\n      {\n        \"category\": \"Application B Enhancements\",\n        \"articles\": [\n          {\n            \"headline\": \"Application B support\",\n            \"description\": \"Introduces CDM support for Application B. Single tenant configuration can now be automatically protected using storage snapshot.\",\n            \"benefit\": \"Protect your latest version of Application B using Product Copy Data Management\",\n            \"id\": \"id string\",\n            \"date\": \"09/10/2017\"\n          },\n          {\n            \"headline\": \"Recovery improvements\",\n            \"description\": \"Product now enables Instant recovery of Application B database to original location from the UI portal.\",\n            \"benefit\": \"Flexible recovery options\",\n            \"id\": \"id string\",\n            \"date\": \"09/10/2017\"\n          }\n        ]\n      },\n      {\n        \"category\": \"Application C support\",\n        \"articles\": [\n          {\n            \"headline\": \"Application C support\",\n            \"description\": \"Product now supports Application C configurations running 9 and above.\",\n            \"benefit\": \"Automatically and efficiently initialize AlwaysOn availability group.\",\n            \"id\": \"id string\",\n            \"date\": \"09/10/2017\"\n          }\n        ]\n      }\n    ]\n  }\n]\n"
  },
  {
    "path": "src/assets/api/port-model.json",
    "content": "[\n\n  {\n    \"serviceName\": \"Secure Shell (SSH) \",\n    \"portNumber\": \"22\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Secure Shell (SSH)\"\n  },\n  {\n    \"serviceName\": \"sunrpc\",\n    \"portNumber\": \"111\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Remote Procedure Call (RPC) port binding.\"\n  },\n  {\n    \"serviceName\": \"LDAP\",\n    \"portNumber\": \"389\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Default LDAP port.\"\n\n  },\n  {\n    \"serviceName\": \"Default TLS port\",\n    \"portNumber\": \"443\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Default web server secure port used with SPP, VCenter and ESX Hosts\"\n\n  },\n  {\n    \"serviceName\": \"LDAP (TLS)\",\n    \"portNumber\": \"636\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Default LDAP support that encrypts data in flight using TLS.\"\n\n  },\n  {\n    \"serviceName\": \"nfs\",\n    \"portNumber\": \"2049\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Used for NFS data transfer to/from vSnap.\"\n  },\n  {\n    \"serviceName\": \"iSCSI\",\n    \"portNumber\": \"3260\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Used for iSCSI data transfer to/from vSnap.\"\n  },\n  {\n    \"serviceName\": \"mountd\",\n    \"portNumber\": \"20048\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"NFS mount protocol\"\n  },\n  {\n    \"serviceName\": \"VADP Proxy\",\n    \"portNumber\": \"8080\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"VMware VM data mover management interface. \"\n  },\n  {\n    \"serviceName\": \"vSnap\",\n    \"portNumber\": \"8900\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"VSnap management service\"\n  },\n  {\n    \"serviceName\": \"VADP Proxy on vSnap node\",\n    \"portNumber\": \"8098\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"VMware VM data mover management interface running on vSnap\"\n  },\n  {\n    \"serviceName\": \"ESXI Network File Copy (NFC)\",\n    \"portNumber\": \"902\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"ESXI Network File Copy (NFC)\"\n  },\n  {\n    \"serviceName\": \"Discovery Service\",\n    \"portNumber\": \"8761\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Automatically discovers VADP proxies and is used by IBM Spectrum Protect Plus VM backup operations.\"\n  },\n  {\n    \"serviceName\": \"Rabbit MQ\",\n    \"portNumber\": \"5671\",\n    \"transportProtocol\": \"tcp\",\n    \"description\": \"Message framework used for communicating asynchronous events.\"\n  }\n\n]\n"
  },
  {
    "path": "src/assets/api/stat-database-model.json",
    "content": "{\n  \"name\":\"Databases\",\n  \"total\":200,\n  \"protected\":100,\n  \"percentProtected\":40,\n  \"icon\":\"database icon\",\n  \"color\":\"orange\"\n}\n"
  },
  {
    "path": "src/assets/api/stat-job-model.json",
    "content": "{\n  \"name\":\"Jobs\",\n  \"total\":50,\n  \"protected\":50,\n  \"percentProtected\":40,\n  \"icon\":\"settings icon\",\n  \"color\":\"blue\"\n}\n"
  },
  {
    "path": "src/assets/api/stat-undefined-model.json",
    "content": "{\n  \"name\":\"Virtual Machines\",\n  \"total\":565,\n  \"protected\":200,\n  \"percentProtected\":40,\n  \"icon\":\"desktop icon\"\n}\n"
  },
  {
    "path": "src/assets/api/stat-vm-model.json",
    "content": "{\n  \"name\":\"Virtual Machines\",\n  \"total\":565,\n  \"protected\":200,\n  \"percentProtected\":40,\n  \"icon\":\"desktop icon\",\n  \"color\":\"green\"\n}\n"
  },
  {
    "path": "src/assets/api/stat-volume-model.json",
    "content": "{\n  \"name\":\"Volumes\",\n  \"total\":252,\n  \"protected\":70,\n  \"percentProtected\":30,\n  \"icon\":\"hdd outline icon\",\n  \"color\":\"purple\"\n}\n"
  },
  {
    "path": "src/assets/api/storage-model.json",
    "content": "{\n  \"volumes\": [\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1356808419\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_200\",\n      \"protocolType\": \"NFS\",\n      \"total\": 699,\n      \"allocated\": 559,\n      \"available\": 140,\n      \"fileCount\": 73743181,\n      \"vmCount\": 20,\n      \"snapshotCount\": 94,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"50336434\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_272\",\n      \"protocolType\": \"CIFS\",\n      \"total\": 131,\n      \"allocated\": 104,\n      \"available\": 27,\n      \"fileCount\": 140916696,\n      \"vmCount\": 65,\n      \"snapshotCount\": 164,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"cifs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1400372106\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_525\",\n      \"protocolType\": \"MIXED\",\n      \"total\": 554,\n      \"allocated\": 443,\n      \"available\": 111,\n      \"fileCount\": 674658385,\n      \"vmCount\": 27,\n      \"snapshotCount\": 133,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"mixed\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"438801716\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_961\",\n      \"protocolType\": \"NFS\",\n      \"total\": 1688,\n      \"allocated\": 1350,\n      \"available\": 338,\n      \"fileCount\": 509518383,\n      \"vmCount\": 100,\n      \"snapshotCount\": 51,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"179172896\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_673\",\n      \"protocolType\": \"CIFS\",\n      \"total\": 188,\n      \"allocated\": 150,\n      \"available\": 38,\n      \"fileCount\": 1423354710,\n      \"vmCount\": 41,\n      \"snapshotCount\": 170,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"cifs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1863489116\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_494\",\n      \"protocolType\": \"MIXED\",\n      \"total\": 1478,\n      \"allocated\": 1182,\n      \"available\": 296,\n      \"fileCount\": 2055981538,\n      \"vmCount\": 24,\n      \"snapshotCount\": 218,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"mixed\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"679542288\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_141\",\n      \"protocolType\": \"NFS\",\n      \"total\": 1576,\n      \"allocated\": 1260,\n      \"available\": 316,\n      \"fileCount\": 484598180,\n      \"vmCount\": 91,\n      \"snapshotCount\": 91,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1448008057\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_865\",\n      \"protocolType\": \"CIFS\",\n      \"total\": 187,\n      \"allocated\": 149,\n      \"available\": 38,\n      \"fileCount\": 1455150084,\n      \"vmCount\": 69,\n      \"snapshotCount\": 29,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"cifs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"107331726\",\n      \"poolId\": \"510143747\",\n      \"policyId\": \"Policy_506\",\n      \"protocolType\": \"MIXED\",\n      \"total\": 1060,\n      \"allocated\": 848,\n      \"available\": 212,\n      \"fileCount\": 888401401,\n      \"vmCount\": 96,\n      \"snapshotCount\": 121,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"mixed\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1696309046\",\n      \"poolId\": \"684805883\",\n      \"policyId\": \"Policy_807\",\n      \"protocolType\": \"NFS\",\n      \"total\": 490,\n      \"allocated\": 392,\n      \"available\": 98,\n      \"fileCount\": 981393962,\n      \"vmCount\": 82,\n      \"snapshotCount\": 175,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"467763111\",\n      \"poolId\": \"684805883\",\n      \"policyId\": \"Policy_434\",\n      \"protocolType\": \"CIFS\",\n      \"total\": 464,\n      \"allocated\": 371,\n      \"available\": 93,\n      \"fileCount\": 1683837460,\n      \"vmCount\": 40,\n      \"snapshotCount\": 41,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"cifs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"892564621\",\n      \"poolId\": \"684805883\",\n      \"policyId\": \"Policy_383\",\n      \"protocolType\": \"MIXED\",\n      \"total\": 1981,\n      \"allocated\": 1584,\n      \"available\": 397,\n      \"fileCount\": 705071166,\n      \"vmCount\": 61,\n      \"snapshotCount\": 241,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"mixed\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1805386240\",\n      \"poolId\": \"684805883\",\n      \"policyId\": \"Policy_644\",\n      \"protocolType\": \"NFS\",\n      \"total\": 823,\n      \"allocated\": 658,\n      \"available\": 165,\n      \"fileCount\": 1184142679,\n      \"vmCount\": 77,\n      \"snapshotCount\": 42,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"744675109\",\n      \"poolId\": \"2072746734\",\n      \"policyId\": \"Policy_927\",\n      \"protocolType\": \"NFS\",\n      \"total\": 2022,\n      \"allocated\": 1617,\n      \"available\": 405,\n      \"fileCount\": 1047060306,\n      \"vmCount\": 19,\n      \"snapshotCount\": 145,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1984542573\",\n      \"poolId\": \"2072746734\",\n      \"policyId\": \"Policy_940\",\n      \"protocolType\": \"CIFS\",\n      \"total\": 386,\n      \"allocated\": 308,\n      \"available\": 78,\n      \"fileCount\": 1535796442,\n      \"vmCount\": 19,\n      \"snapshotCount\": 111,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"cifs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1594459696\",\n      \"poolId\": \"2072746734\",\n      \"policyId\": \"Policy_812\",\n      \"protocolType\": \"MIXED\",\n      \"total\": 1303,\n      \"allocated\": 1042,\n      \"available\": 261,\n      \"fileCount\": 1423752387,\n      \"vmCount\": 51,\n      \"snapshotCount\": 92,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"mixed\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1119961550\",\n      \"poolId\": \"2072746734\",\n      \"policyId\": \"Policy_211\",\n      \"protocolType\": \"NFS\",\n      \"total\": 656,\n      \"allocated\": 524,\n      \"available\": 132,\n      \"fileCount\": 1425203788,\n      \"vmCount\": 31,\n      \"snapshotCount\": 188,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1888422731\",\n      \"poolId\": \"2072746734\",\n      \"policyId\": \"Policy_239\",\n      \"protocolType\": \"CIFS\",\n      \"total\": 791,\n      \"allocated\": 632,\n      \"available\": 159,\n      \"fileCount\": 917272960,\n      \"vmCount\": 74,\n      \"snapshotCount\": 10,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"cifs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"1639523587\",\n      \"poolId\": \"2072746734\",\n      \"policyId\": \"Policy_391\",\n      \"protocolType\": \"MIXED\",\n      \"total\": 1197,\n      \"allocated\": 957,\n      \"available\": 240,\n      \"fileCount\": 1765944241,\n      \"vmCount\": 20,\n      \"snapshotCount\": 166,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"mixed\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"396800785\",\n      \"poolId\": \"1367767837\",\n      \"policyId\": \"Policy_177\",\n      \"protocolType\": \"NFS\",\n      \"total\": 1350,\n      \"allocated\": 1080,\n      \"available\": 270,\n      \"fileCount\": 940273680,\n      \"vmCount\": 60,\n      \"snapshotCount\": 66,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"2082371931\",\n      \"poolId\": \"1367767837\",\n      \"policyId\": \"Policy_53\",\n      \"protocolType\": \"CIFS\",\n      \"total\": 2016,\n      \"allocated\": 1612,\n      \"available\": 404,\n      \"fileCount\": 1899545025,\n      \"vmCount\": 94,\n      \"snapshotCount\": 36,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"cifs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"ZFSVOLUME\",\n      \"timestamp\": 1511668600434,\n      \"volumeId\": \"387140983\",\n      \"poolId\": \"1367767837\",\n      \"policyId\": \"Policy_142\",\n      \"protocolType\": \"MIXED\",\n      \"total\": 1318,\n      \"allocated\": 1054,\n      \"available\": 264,\n      \"fileCount\": 128550758,\n      \"vmCount\": 69,\n      \"snapshotCount\": 202,\n      \"compressionRatio\": 2.5,\n      \"dedupeEfficiency\": 25,\n      \"name\": \"ZFSVOLUME\",\n      \"description\": \"ZFS Volume Description.\",\n      \"icon\": \"assets/images/volume.png\",\n      \"tags\": [\n        {\n          \"facet\": \"Protocol\",\n          \"name\": \"nfs\"\n        },\n        {\n          \"facet\": \"Range\",\n          \"name\": \"allocated\"\n        }\n      ],\n      \"actions\": [\n        {\n          \"name\": \"view policy\"\n        }\n      ]\n    }\n  ]\n}\n\n"
  },
  {
    "path": "src/assets/api/todo-model.json",
    "content": "{\n  \"name\":\"Todo\",\n  \"value\":\"Example service data!\"\n}\n"
  },
  {
    "path": "src/assets/api/trend-model.json",
    "content": "{\n  \"data\": [\n    {\n      \"name\": \"Resource A\",\n      \"series\": [\n        {\n          \"name\": \"January\",\n          \"value\": 3453\n        },\n        {\n          \"name\": \"February\",\n          \"value\": 3434434\n        },\n        {\n          \"name\": \"March\",\n          \"value\": 333335\n        },\n        {\n          \"name\": \"April\",\n          \"value\": 434\n        }\n      ]\n    },\n    {\n      \"name\": \"Resource B\",\n      \"series\": [\n        {\n          \"name\": \"January\",\n          \"value\": 78\n        },\n        {\n          \"name\": \"February\",\n          \"value\": 82700\n        },\n        {\n          \"name\": \"March\",\n          \"value\": 4333335\n        },\n        {\n          \"name\": \"April\",\n          \"value\": 8345\n        }\n      ]\n    },\n    {\n      \"name\": \"Resource C\",\n      \"series\": [\n        {\n          \"name\": \"January\",\n          \"value\": 5043344\n        },\n        {\n          \"name\": \"February\",\n          \"value\": 5800\n        },\n        {\n          \"name\": \"March\",\n          \"value\": 333335\n        },\n        {\n          \"name\": \"April\",\n          \"value\": 4343333\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/assets/api/trendline-help-model.json",
    "content": "{\n  \"heading\": \"Trends\",\n  \"summary\": \"\",\n  \"details\": [\n    {\n      \"category\": \"IOPS\",\n      \"articles\": [\n        {\n          \"headline\": \"IOPS\",\n          \"description\": \"ECX enables automated seeding of your SQL Server AlwaysON availability group by leveraging Storage snapshot technology to minimize the data movement between primary and secondary replica.\",\n          \"benefit\": \"Automatically and efficiently initialize AlwaysOn availability group.\",\n          \"id\": \"id string\",\n          \"date\": \"09/10/2017\"\n        }\n      ]\n    },\n    {\n      \"category\": \"CPU\",\n      \"articles\": [\n        {\n          \"headline\": \"SAP HANA 2.0 support\",\n          \"description\": \"ECX 2.7 introduces CDM support for SAP HANA 2.0 SPS01. Single tenant configuration can now be automatically protected using storage snapshot.\",\n          \"benefit\": \"Protect your latest version of SAP HANA using ECX Copy Data Management\",\n          \"id\": \"id string\",\n          \"date\": \"09/10/2017\"\n        },\n        {\n          \"headline\": \"Recovery improvements\",\n          \"description\": \"ECX now enables Instant recovery of SAP HANA database to original location from the UI portal.\",\n          \"benefit\": \"Flexible recovery options\",\n          \"id\": \"id string\",\n          \"date\": \"09/10/2017\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "src/assets/api/version-model.json",
    "content": "[\n  {\n    \"name\": \"metric 1\",\n    \"series\": [\n      {\n        \"name\": \"used\",\n        \"value\": 75\n      },\n      {\n        \"name\": \"available\",\n        \"value\": 100\n      }\n    ]\n  },\n  {\n    \"name\": \"metric 2\",\n    \"series\": [\n      {\n        \"name\": \"used\",\n        \"value\": 23\n      },\n      {\n        \"name\": \"available\",\n        \"value\": 77\n      }\n    ]\n  }\n]"
  },
  {
    "path": "src/environments/environment.prod.ts",
    "content": "export const environment = {\n    production: true,\n    productName: \"Dynamic Dashboard Framework\",\n    productVersion: \"0.0.4\",\n    menu:{\n        documentation:false,\n        ai: false,\n        notification:false\n    },\n    boardConfiguration:{\n        board:true,\n        ai:false,\n        endpoint:true\n    }\n\n};\n"
  },
  {
    "path": "src/environments/environment.ts",
    "content": "// The file contents for the current environment will overwrite these during build.\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\n// The list of which env maps to which file can be found in `.angular-cli.json`.\n\nexport const environment = {\n    production: false,\n    productName: \"Dynamic Dashboard Framework\",\n    productVersion: \"0.0.5\",\n    menu:{\n        documentation:true,\n        aiSearch: true,\n        notification:true\n    },\n    boardConfiguration:{\n        board:true,\n        ai:true,\n        endpoint:true\n    }\n};\n\n\n"
  },
  {
    "path": "src/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>NGX Dynamic Dashboard Framework </title>\n    <base href=\"/\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\">\n</head>\n<body>\n<div class=\"pusher\" style=\"background-color: whitesmoke !important\">\n    <app-root></app-root>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "src/main.ts",
    "content": "import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n  enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule);\n"
  },
  {
    "path": "src/polyfills.ts",
    "content": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfills to this file.\n *\n * This file is divided into 2 sections:\n *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\n *   2. Application imports. Files imported after ZoneJS that should be loaded before your main\n *      file.\n *\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\n * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),\n * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.\n *\n * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html\n */\n\n/***************************************************************************************************\n * BROWSER POLYFILLS\n */\n\n/** IE9, IE10 and IE11 requires all of the following polyfills. **/\n// import 'core-js/es6/symbol';\n// import 'core-js/es6/object';\n// import 'core-js/es6/function';\n// import 'core-js/es6/parse-int';\n// import 'core-js/es6/parse-float';\n// import 'core-js/es6/number';\n// import 'core-js/es6/math';\n// import 'core-js/es6/string';\n// import 'core-js/es6/date';\n// import 'core-js/es6/array';\n// import 'core-js/es6/regexp';\n// import 'core-js/es6/map';\n// import 'core-js/es6/set';\n\n/** IE10 and IE11 requires the following for NgClass support on SVG elements */\n// import 'classlist.js';  // Run `npm install --save classlist.js`.\n\n/** IE10 and IE11 requires the following to support `@angular/animation`. */\n// import 'web-animations-js';  // Run `npm install --save web-animations-js`.\n\n\n/** Evergreen browsers require these. **/\nimport 'core-js/es6/reflect';\n\n\n\n/** ALL Firefox browsers require the following to support `@angular/animation`. **/\n// import 'web-animations-js';  // Run `npm install --save web-animations-js`.\n\n\n\n/***************************************************************************************************\n * Zone JS is required by Angular itself.\n */\nimport 'zone.js/dist/zone';  // Included with Angular CLI.\n\n\n\n/***************************************************************************************************\n * APPLICATION IMPORTS\n */\n\n/**\n * Date, currency, decimal and percent pipes.\n * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10\n */\n// import 'intl';  // Run `npm install --save intl`.\n"
  },
  {
    "path": "src/styles.css",
    "content": "/* You can add global styles to this file, and also import other style files */\n@import \"~@angular/material/prebuilt-themes/indigo-pink.css\";\nbody{\n    background-color: whitesmoke !important;\n    font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif !important;\n    color:darkgray !important;\n}\n\nh1, h2{\n    color: #6e6e6e !important;\n}"
  },
  {
    "path": "src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/long-stack-trace-zone';\nimport 'zone.js/dist/proxy.js';\nimport 'zone.js/dist/sync-test';\nimport 'zone.js/dist/jasmine-patch';\nimport 'zone.js/dist/async-test';\nimport 'zone.js/dist/fake-async-test';\nimport { getTestBed } from '@angular/core/testing';\nimport {\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting\n} from '@angular/platform-browser-dynamic/testing';\n\n// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.\ndeclare var __karma__: any;\ndeclare var require: any;\n\n// Prevent Karma from running prematurely.\n__karma__.loaded = function () {};\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(\n  BrowserDynamicTestingModule,\n  platformBrowserDynamicTesting()\n);\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n// Finally, start Karma to run the tests.\n__karma__.start();\n"
  },
  {
    "path": "src/tsconfig.app.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/app\",\n    \"module\": \"es2015\",\n    \"baseUrl\": \"\",\n    \"types\": [\n    ]\n  },\n  \"exclude\": [\n    \"test.ts\",\n    \"**/*.spec.ts\"\n  ]\n}\n"
  },
  {
    "path": "src/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/spec\",\n    \"module\": \"commonjs\",\n    \"target\": \"es5\",\n    \"baseUrl\": \"\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"test.ts\",\n    \"polyfills.ts\"\n  ],\n  \"include\": [\n    \"**/*.spec.ts\",\n    \"**/*.d.ts\"\n  ]\n}\n"
  },
  {
    "path": "src/typings.d.ts",
    "content": "/* SystemJS module definition */\ndeclare var module: NodeModule;\ninterface NodeModule {\n  id: string;\n}\ndeclare module 'sockjs-client';\ndeclare module 'stompjs';\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"importHelpers\": true,\n    \"outDir\": \"./dist/out-tsc\",\n    \"baseUrl\": \"src\",\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"moduleResolution\": \"node\",\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"target\": \"es5\",\n    \"typeRoots\": [\n      \"node_modules/@types\"\n    ],\n    \"lib\": [\n      \"es2016\",\n      \"dom\"\n    ]\n  }\n}\n"
  },
  {
    "path": "tslint.json",
    "content": "{\n  \"rulesDirectory\": [\n    \"node_modules/codelyzer\"\n  ],\n  \"rules\": {\n    \"callable-types\": true,\n    \"class-name\": true,\n    \"comment-format\": [\n      true,\n      \"check-space\"\n    ],\n    \"curly\": true,\n    \"eofline\": true,\n    \"forin\": true,\n    \"import-blacklist\": [true],\n    \"import-spacing\": true,\n    \"indent\": [\n      true,\n      \"spaces\"\n    ],\n    \"interface-over-type-literal\": true,\n    \"label-position\": true,\n    \"max-line-length\": [\n      true,\n      140\n    ],\n    \"member-access\": false,\n    \"member-ordering\": [\n      true,\n      \"static-before-instance\",\n      \"variables-before-functions\"\n    ],\n    \"no-arg\": true,\n    \"no-bitwise\": true,\n    \"no-console\": [\n      false,\n      \"debug\",\n      \"info\",\n      \"time\",\n      \"timeEnd\",\n      \"trace\"\n    ],\n    \"no-construct\": true,\n    \"no-debugger\": true,\n    \"no-duplicate-variable\": true,\n    \"no-empty\": false,\n    \"no-empty-interface\": true,\n    \"no-eval\": true,\n    \"no-inferrable-types\": [true, \"ignore-params\"],\n    \"no-shadowed-variable\": true,\n    \"no-string-literal\": false,\n    \"no-string-throw\": true,\n    \"no-switch-case-fall-through\": true,\n    \"no-trailing-whitespace\": true,\n    \"no-unused-expression\": true,\n    \"no-use-before-declare\": true,\n    \"no-var-keyword\": true,\n    \"object-literal-sort-keys\": false,\n    \"one-line\": [\n      true,\n      \"check-open-brace\",\n      \"check-catch\",\n      \"check-else\",\n      \"check-whitespace\"\n    ],\n    \"prefer-const\": true,\n    \"quotemark\": [\n      true,\n      \"single\"\n    ],\n    \"radix\": true,\n    \"semicolon\": [\n      \"always\"\n    ],\n    \"triple-equals\": [\n      true,\n      \"allow-null-check\"\n    ],\n    \"typedef-whitespace\": [\n      true,\n      {\n        \"call-signature\": \"nospace\",\n        \"index-signature\": \"nospace\",\n        \"parameter\": \"nospace\",\n        \"property-declaration\": \"nospace\",\n        \"variable-declaration\": \"nospace\"\n      }\n    ],\n    \"typeof-compare\": true,\n    \"unified-signatures\": true,\n    \"variable-name\": false,\n    \"whitespace\": [\n      true,\n      \"check-branch\",\n      \"check-decl\",\n      \"check-operator\",\n      \"check-separator\",\n      \"check-type\"\n    ],\n\n    \"directive-selector\": [true, \"attribute\", \"app\", \"camelCase\"],\n    \"component-selector\": [true, \"element\", \"app\", \"kebab-case\"],\n    \"use-input-property-decorator\": true,\n    \"use-output-property-decorator\": true,\n    \"use-host-property-decorator\": true,\n    \"no-input-rename\": true,\n    \"no-output-rename\": true,\n    \"use-life-cycle-interface\": true,\n    \"use-pipe-transform-interface\": true,\n    \"component-class-suffix\": true,\n    \"directive-class-suffix\": true,\n    \"no-access-missing-member\": true,\n    \"templates-use-public\": true,\n    \"invoke-injectable\": true\n  }\n}\n"
  }
]