You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2018/11/16 22:00:12 UTC

[airavata-django-portal] branch master updated (1d847ad -> d30077b)

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git.


    from 1d847ad  AIRAVATA-2711 Removing Autocomplete.vue component
     new aa81587  AIRAVATA-2907 GatewayResourceProfile editor UI
     new 5236001  AIRAVATA-2907 Add new storage preference UI
     new da40a7b  AIRAVATA-2907 Only allow Admins to edit GatewayResourceProfile
     new dd63cc1  AIRAVATA-2907 Better default ssh key description; filter storage options
     new fd358e4  AIRAVATA-2907 Formatting storage pref listing
     new d30077b  AIRAVATA-2907 Delete storage prefs

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 django_airavata/apps/admin/package-lock.json       | 2142 +++++++++++++++-----
 .../ComputePreference.vue                          |   19 +-
 .../GroupComputeResourcePreference.vue             |    3 -
 .../credentials/SSHCredentialSelector.vue          |   51 +-
 .../GatewayResourceProfileEditor.vue               |   28 +
 .../GatewayResourceProfileEditorContainer.vue      |  105 +
 .../gatewayprofile/StoragePreferenceEditor.vue     |   43 +
 .../gatewayprofile/StoragePreferenceList.vue       |  201 ++
 .../static/django_airavata_admin/src/router.js     |    6 +
 .../apps/admin/templates/admin/admin_base.html     |    5 +
 django_airavata/apps/admin/urls.py                 |    2 +
 django_airavata/apps/admin/views.py                |    6 +
 django_airavata/apps/api/serializers.py            |   54 +-
 .../api/static/django_airavata_api/js/index.js     |    5 +
 .../js/models/GatewayResourceProfile.js            |   21 +
 .../js/models/StoragePreference.js                 |   14 +
 .../js/models/StorageResourceDescription.js        |   17 +
 .../django_airavata_api/js/service_config.js       |   49 +
 django_airavata/apps/api/thrift_utils.py           |   10 +-
 django_airavata/apps/api/urls.py                   |   11 +
 django_airavata/apps/api/views.py                  |   93 +
 .../static/common/js/layouts/ListLayout.vue        |    5 +
 22 files changed, 2310 insertions(+), 580 deletions(-)
 create mode 100644 django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue
 create mode 100644 django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
 create mode 100644 django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
 create mode 100644 django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
 create mode 100644 django_airavata/apps/api/static/django_airavata_api/js/models/GatewayResourceProfile.js
 create mode 100644 django_airavata/apps/api/static/django_airavata_api/js/models/StoragePreference.js
 create mode 100644 django_airavata/apps/api/static/django_airavata_api/js/models/StorageResourceDescription.js


[airavata-django-portal] 01/06: AIRAVATA-2907 GatewayResourceProfile editor UI

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit aa81587174214d44079579ec8b43636e40fef563
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Thu Nov 8 15:00:26 2018 -0500

    AIRAVATA-2907 GatewayResourceProfile editor UI
---
 django_airavata/apps/admin/package-lock.json       | 2142 +++++++++++++++-----
 .../credentials/SSHCredentialSelector.vue          |    3 +
 .../GatewayResourceProfileEditor.vue               |   32 +
 .../GatewayResourceProfileEditorContainer.vue      |   87 +
 .../gatewayprofile/StoragePreferenceEditor.vue     |   42 +
 .../gatewayprofile/StoragePreferenceList.vue       |  106 +
 .../gatewayprofile/StoragePreferenceListItem.vue   |   10 +
 .../static/django_airavata_admin/src/router.js     |    6 +
 .../apps/admin/templates/admin/admin_base.html     |    3 +
 django_airavata/apps/admin/urls.py                 |    2 +
 django_airavata/apps/admin/views.py                |    6 +
 django_airavata/apps/api/serializers.py            |   37 +-
 .../api/static/django_airavata_api/js/index.js     |    3 +
 .../js/models/GatewayResourceProfile.js            |   21 +
 .../js/models/StoragePreference.js                 |   14 +
 .../django_airavata_api/js/service_config.js       |   28 +
 django_airavata/apps/api/thrift_utils.py           |   10 +-
 django_airavata/apps/api/urls.py                   |    6 +
 django_airavata/apps/api/views.py                  |   41 +
 19 files changed, 2037 insertions(+), 562 deletions(-)

diff --git a/django_airavata/apps/admin/package-lock.json b/django_airavata/apps/admin/package-lock.json
index 2603d83..85879c7 100644
--- a/django_airavata/apps/admin/package-lock.json
+++ b/django_airavata/apps/admin/package-lock.json
@@ -5,52 +5,49 @@
   "requires": true,
   "dependencies": {
     "@fortawesome/fontawesome-common-types": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.4.tgz",
-      "integrity": "sha512-0qbIVm+MzkxMwKDx8V0C7w/6Nk+ZfBseOn2R1YK0f2DQP5pBcOQbu9NmaVaLzbJK6VJb1TuyTf0ZF97rc6iWJQ=="
+      "version": "0.2.8",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.8.tgz",
+      "integrity": "sha512-0sU7JDLdEeGQlWBSr5uEE6PZOM15YM1s9rFlpZV+WhNdX2V6Co3Sj0OW5el4F54X1Tw+nfxf4Cc3dUedudaDWg=="
     },
     "@fortawesome/fontawesome-svg-core": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.4.tgz",
-      "integrity": "sha512-oGtnwcdhJomoDxbJcy6S0JxK6ItDhJLNOujm+qILPqajJ2a0P/YRomzBbixFjAPquCoyPUlA9g9ejA22P7TKNA==",
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.8.tgz",
+      "integrity": "sha512-cvcMQZ5F8WSNSGMk9uWlkmZNfDzmdsWLRrTMrNwwihHcEmWRlIuSbDt+PQ/rXsnGmJnmLQJLFBT1cse/3swxbg==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "^0.2.4"
+        "@fortawesome/fontawesome-common-types": "^0.2.8"
       }
     },
     "@fortawesome/free-regular-svg-icons": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.3.1.tgz",
-      "integrity": "sha512-ZHMohHUxPSEUeqc7LOmO5jdeI3vlQLDgSCYR4MYk6oN7C3X59vUadLefnvctMTJyF5NWYxDbaj90ulvickDnsQ==",
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.5.0.tgz",
+      "integrity": "sha512-qXOglmsMJR3a//AtfTHYaAITODuTDV73IDtU95diP//wSU+md8umWryB6B38S9b5ECvH8eMN1zLa+np2Pw564g==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "^0.2.4"
+        "@fortawesome/fontawesome-common-types": "^0.2.8"
       }
     },
     "@fortawesome/free-solid-svg-icons": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.3.1.tgz",
-      "integrity": "sha512-NkiLBFoiHtJ89cPJdM+W6cLvTVKkLh3j9t3MxkXyip0ncdD3lhCunSuzvFcrTHWeETEyoClGd8ZIWrr3HFZ3BA==",
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.5.0.tgz",
+      "integrity": "sha512-VawIT2owNP97EwehZmxkvZDhoKwEevU/1HOMkln6kc4OtfE+JKYr6DpyzQnHVWXvz/eFj36QElHNe6zT8gR+Tg==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "^0.2.4"
+        "@fortawesome/fontawesome-common-types": "^0.2.8"
       }
     },
     "@fortawesome/vue-fontawesome": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-0.1.1.tgz",
-      "integrity": "sha512-dvPpA9eI18bWr3E+c0JvCYD6xl/keEj0ICTMShUPbxsGkd6PdFU9xYjqA8qE8ahsY+xhbQzZt/k1FKlpMGaRXA=="
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-0.1.2.tgz",
+      "integrity": "sha512-K/3awMf8AZmTyiYfNVuTHAtjToro6tE/yNV8dsmFk/2v6CXj+6wGltMzX8VBF9vC9rz3iv1zTwMdwtYaQYrAmQ=="
     },
     "@sindresorhus/is": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
       "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow=="
     },
-    "@types/commander": {
-      "version": "2.12.2",
-      "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz",
-      "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==",
-      "dev": true,
-      "requires": {
-        "commander": "*"
-      }
+    "@types/node": {
+      "version": "10.12.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.3.tgz",
+      "integrity": "sha512-sfGmOtSMSbQ/AKG8V9xD1gmjquC9awIIZ/Kj309pHb2n3bcRAcGMQv5nJ6gCXZVsneGE4+ve8DXKRCsrg3TFzg==",
+      "dev": true
     },
     "@types/semver": {
       "version": "5.5.0",
@@ -134,7 +131,7 @@
     },
     "ansi-escapes": {
       "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+      "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
       "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4="
     },
     "ansi-html": {
@@ -536,7 +533,7 @@
         },
         "util": {
           "version": "0.10.3",
-          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+          "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
           "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
           "dev": true,
           "requires": {
@@ -1511,9 +1508,9 @@
       "dev": true
     },
     "bluebird": {
-      "version": "3.5.2",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
-      "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==",
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
+      "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
       "dev": true
     },
     "bn.js": {
@@ -1523,28 +1520,31 @@
       "dev": true
     },
     "body-parser": {
-      "version": "1.18.2",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
-      "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
+      "version": "1.18.3",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
+      "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
       "dev": true,
       "requires": {
         "bytes": "3.0.0",
         "content-type": "~1.0.4",
         "debug": "2.6.9",
-        "depd": "~1.1.1",
-        "http-errors": "~1.6.2",
-        "iconv-lite": "0.4.19",
+        "depd": "~1.1.2",
+        "http-errors": "~1.6.3",
+        "iconv-lite": "0.4.23",
         "on-finished": "~2.3.0",
-        "qs": "6.5.1",
-        "raw-body": "2.3.2",
-        "type-is": "~1.6.15"
+        "qs": "6.5.2",
+        "raw-body": "2.3.3",
+        "type-is": "~1.6.16"
       },
       "dependencies": {
         "iconv-lite": {
-          "version": "0.4.19",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
-          "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
-          "dev": true
+          "version": "0.4.23",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+          "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+          "dev": true,
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
         }
       }
     },
@@ -1723,7 +1723,7 @@
     },
     "cacache": {
       "version": "10.0.4",
-      "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+      "resolved": "http://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
       "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
       "dev": true,
       "requires": {
@@ -1829,15 +1829,15 @@
       }
     },
     "caniuse-db": {
-      "version": "1.0.30000888",
-      "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000888.tgz",
-      "integrity": "sha512-bp7cHptv4AQZFtkyzYk2bJN5E8CSYklm6K3bJ/fGUa52oxydzBKK4uYlZ+A0lNIiThRFJMoXU2TacG9ve2KpXw==",
+      "version": "1.0.30000907",
+      "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000907.tgz",
+      "integrity": "sha512-OKtlTmEPR9GgCxnKMlvdHTT2QD6n4eIovcVqEnjoR8iB9l6rk4abKnjsDSyTD36an/ebgigl8T2CSdwSf4JoGw==",
       "dev": true
     },
     "caniuse-lite": {
-      "version": "1.0.30000888",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000888.tgz",
-      "integrity": "sha512-vftg+5p/lPsQGpnhSo/yBuYL36ai/cyjLvU3dOPJY1kkKrekLWIy8SLm+wzjX0hpCUdFTasC4/ZT7uqw4rKOnQ==",
+      "version": "1.0.30000907",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000907.tgz",
+      "integrity": "sha512-No5sQ/OB2Nmka8MNOOM6nJx+Hxt6MQ6h7t7kgJFu9oTuwjykyKRSBP/+i/QAyFHxeHB+ddE0Da1CG5ihx9oehQ==",
       "dev": true
     },
     "center-align": {
@@ -2161,7 +2161,7 @@
     },
     "color": {
       "version": "0.11.4",
-      "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz",
+      "resolved": "http://registry.npmjs.org/color/-/color-0.11.4.tgz",
       "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=",
       "dev": true,
       "requires": {
@@ -2341,9 +2341,9 @@
       "dev": true
     },
     "copy-webpack-plugin": {
-      "version": "4.5.2",
-      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.2.tgz",
-      "integrity": "sha512-zmC33E8FFSq3AbflTvqvPvBo621H36Afsxlui91d+QyZxPIuXghfnTsa1CuqiAaCPgJoSUWfTFbKJnadZpKEbQ==",
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz",
+      "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==",
       "dev": true,
       "requires": {
         "cacache": "^10.0.4",
@@ -2468,7 +2468,7 @@
     },
     "css-loader": {
       "version": "0.28.11",
-      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz",
+      "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz",
       "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==",
       "dev": true,
       "requires": {
@@ -2546,7 +2546,7 @@
     },
     "css-select": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
       "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
       "dev": true,
       "requires": {
@@ -2557,9 +2557,9 @@
       }
     },
     "css-selector-tokenizer": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
-      "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=",
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
+      "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
       "dev": true,
       "requires": {
         "cssesc": "^0.1.0",
@@ -2581,9 +2581,9 @@
       }
     },
     "css-what": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
-      "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz",
+      "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==",
       "dev": true
     },
     "cssesc": {
@@ -4657,13 +4657,155 @@
         "vue": "^2.3.3"
       },
       "dependencies": {
-        "@types/commander": {
-          "version": "2.12.2",
+        "@babel/code-frame": {
+          "version": "7.0.0",
+          "bundled": true,
+          "requires": {
+            "@babel/highlight": "^7.0.0"
+          }
+        },
+        "@babel/generator": {
+          "version": "7.1.3",
+          "bundled": true,
+          "requires": {
+            "@babel/types": "^7.1.3",
+            "jsesc": "^2.5.1",
+            "lodash": "^4.17.10",
+            "source-map": "^0.5.0",
+            "trim-right": "^1.0.1"
+          },
+          "dependencies": {
+            "jsesc": {
+              "version": "2.5.1",
+              "bundled": true
+            }
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.1.0",
+          "bundled": true,
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.0.0",
+            "@babel/template": "^7.1.0",
+            "@babel/types": "^7.0.0"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.0.0",
+          "bundled": true,
+          "requires": {
+            "@babel/types": "^7.0.0"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.0.0",
+          "bundled": true,
+          "requires": {
+            "@babel/types": "^7.0.0"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.0.0",
+          "bundled": true,
+          "requires": {
+            "chalk": "^2.0.0",
+            "esutils": "^2.0.2",
+            "js-tokens": "^4.0.0"
+          },
+          "dependencies": {
+            "ansi-styles": {
+              "version": "3.2.1",
+              "bundled": true,
+              "requires": {
+                "color-convert": "^1.9.0"
+              }
+            },
+            "chalk": {
+              "version": "2.4.1",
+              "bundled": true,
+              "requires": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+              }
+            },
+            "js-tokens": {
+              "version": "4.0.0",
+              "bundled": true
+            },
+            "supports-color": {
+              "version": "5.5.0",
+              "bundled": true,
+              "requires": {
+                "has-flag": "^3.0.0"
+              }
+            }
+          }
+        },
+        "@babel/parser": {
+          "version": "7.1.3",
+          "bundled": true
+        },
+        "@babel/template": {
+          "version": "7.1.2",
+          "bundled": true,
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.1.2",
+            "@babel/types": "^7.1.2"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.1.4",
+          "bundled": true,
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/generator": "^7.1.3",
+            "@babel/helper-function-name": "^7.1.0",
+            "@babel/helper-split-export-declaration": "^7.0.0",
+            "@babel/parser": "^7.1.3",
+            "@babel/types": "^7.1.3",
+            "debug": "^3.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.10"
+          },
+          "dependencies": {
+            "debug": {
+              "version": "3.2.6",
+              "bundled": true,
+              "requires": {
+                "ms": "^2.1.1"
+              }
+            },
+            "globals": {
+              "version": "11.8.0",
+              "bundled": true
+            },
+            "ms": {
+              "version": "2.1.1",
+              "bundled": true
+            }
+          }
+        },
+        "@babel/types": {
+          "version": "7.1.3",
           "bundled": true,
           "requires": {
-            "commander": "*"
+            "esutils": "^2.0.2",
+            "lodash": "^4.17.10",
+            "to-fast-properties": "^2.0.0"
+          },
+          "dependencies": {
+            "to-fast-properties": {
+              "version": "2.0.0",
+              "bundled": true
+            }
           }
         },
+        "@types/node": {
+          "version": "10.12.0",
+          "bundled": true
+        },
         "@types/semver": {
           "version": "5.5.0",
           "bundled": true
@@ -4681,7 +4823,7 @@
           }
         },
         "acorn": {
-          "version": "5.7.3",
+          "version": "6.0.2",
           "bundled": true
         },
         "acorn-dynamic-import": {
@@ -4697,14 +4839,18 @@
             }
           }
         },
+        "acorn-jsx": {
+          "version": "5.0.0",
+          "bundled": true
+        },
         "ajv": {
-          "version": "5.5.2",
+          "version": "6.5.4",
           "bundled": true,
           "requires": {
-            "co": "^4.6.0",
-            "fast-deep-equal": "^1.0.0",
+            "fast-deep-equal": "^2.0.1",
             "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.3.0"
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
           }
         },
         "ajv-keywords": {
@@ -4823,6 +4969,10 @@
           "version": "0.3.2",
           "bundled": true
         },
+        "arrify": {
+          "version": "1.0.1",
+          "bundled": true
+        },
         "asn1": {
           "version": "0.2.4",
           "bundled": true,
@@ -4955,6 +5105,18 @@
             "source-map": "^0.5.7"
           }
         },
+        "babel-eslint": {
+          "version": "9.0.0",
+          "bundled": true,
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "@babel/parser": "^7.0.0",
+            "@babel/traverse": "^7.0.0",
+            "@babel/types": "^7.0.0",
+            "eslint-scope": "3.7.1",
+            "eslint-visitor-keys": "^1.0.0"
+          }
+        },
         "babel-generator": {
           "version": "6.26.1",
           "bundled": true,
@@ -5515,7 +5677,6 @@
         "bcrypt-pbkdf": {
           "version": "1.0.2",
           "bundled": true,
-          "optional": true,
           "requires": {
             "tweetnacl": "^0.14.3"
           }
@@ -5544,28 +5705,27 @@
           "bundled": true
         },
         "body-parser": {
-          "version": "1.18.2",
+          "version": "1.18.3",
           "bundled": true,
           "requires": {
             "bytes": "3.0.0",
             "content-type": "~1.0.4",
             "debug": "2.6.9",
-            "depd": "~1.1.1",
-            "http-errors": "~1.6.2",
-            "iconv-lite": "0.4.19",
+            "depd": "~1.1.2",
+            "http-errors": "~1.6.3",
+            "iconv-lite": "0.4.23",
             "on-finished": "~2.3.0",
-            "qs": "6.5.1",
-            "raw-body": "2.3.2",
-            "type-is": "~1.6.15"
+            "qs": "6.5.2",
+            "raw-body": "2.3.3",
+            "type-is": "~1.6.16"
           },
           "dependencies": {
             "iconv-lite": {
-              "version": "0.4.19",
-              "bundled": true
-            },
-            "qs": {
-              "version": "6.5.1",
-              "bundled": true
+              "version": "0.4.23",
+              "bundled": true,
+              "requires": {
+                "safer-buffer": ">= 2.1.2 < 3"
+              }
             }
           }
         },
@@ -5745,6 +5905,17 @@
             "unset-value": "^1.0.0"
           }
         },
+        "caller-path": {
+          "version": "0.1.0",
+          "bundled": true,
+          "requires": {
+            "callsites": "^0.2.0"
+          }
+        },
+        "callsites": {
+          "version": "0.2.0",
+          "bundled": true
+        },
         "camelcase": {
           "version": "2.1.1",
           "bundled": true
@@ -5778,11 +5949,11 @@
           }
         },
         "caniuse-db": {
-          "version": "1.0.30000888",
+          "version": "1.0.30000898",
           "bundled": true
         },
         "caniuse-lite": {
-          "version": "1.0.30000888",
+          "version": "1.0.30000898",
           "bundled": true
         },
         "caseless": {
@@ -5839,6 +6010,10 @@
             "safe-buffer": "^5.0.1"
           }
         },
+        "circular-json": {
+          "version": "0.3.3",
+          "bundled": true
+        },
         "clap": {
           "version": "1.2.3",
           "bundled": true,
@@ -5988,7 +6163,7 @@
           }
         },
         "commander": {
-          "version": "2.18.0",
+          "version": "2.19.0",
           "bundled": true
         },
         "commondir": {
@@ -6323,6 +6498,10 @@
           "version": "1.0.1",
           "bundled": true
         },
+        "deep-is": {
+          "version": "0.1.3",
+          "bundled": true
+        },
         "define-properties": {
           "version": "1.1.3",
           "bundled": true,
@@ -6368,15 +6547,22 @@
           "bundled": true
         },
         "del": {
-          "version": "3.0.0",
+          "version": "2.2.2",
           "bundled": true,
           "requires": {
-            "globby": "^6.1.0",
+            "globby": "^5.0.0",
             "is-path-cwd": "^1.0.0",
             "is-path-in-cwd": "^1.0.0",
-            "p-map": "^1.1.1",
-            "pify": "^3.0.0",
+            "object-assign": "^4.0.1",
+            "pify": "^2.0.0",
+            "pinkie-promise": "^2.0.0",
             "rimraf": "^2.2.8"
+          },
+          "dependencies": {
+            "pify": {
+              "version": "2.3.0",
+              "bundled": true
+            }
           }
         },
         "delayed-stream": {
@@ -6919,7 +7105,12 @@
                 "core-js": "^2.5.0",
                 "regenerator-runtime": "^0.10.5"
               },
-              "dependencies": {}
+              "dependencies": {
+                "regenerator-runtime": {
+                  "version": "0.10.5",
+                  "bundled": true
+                }
+              }
             },
             "babel-preset-env": {
               "version": "1.7.0",
@@ -7201,85 +7392,536 @@
                 "nan": "^2.9.2",
                 "node-pre-gyp": "^0.10.0"
               },
-              "dependencies": {}
-            },
-            "glob": {
-              "version": "7.1.2",
-              "bundled": true,
-              "requires": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.0.4",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-              }
-            },
-            "glob-base": {
-              "version": "0.3.0",
-              "bundled": true,
-              "optional": true,
-              "requires": {
-                "glob-parent": "^2.0.0",
-                "is-glob": "^2.0.0"
-              }
-            },
-            "glob-parent": {
-              "version": "2.0.0",
-              "bundled": true,
-              "requires": {
-                "is-glob": "^2.0.0"
-              }
-            },
-            "globals": {
-              "version": "9.18.0",
-              "bundled": true
-            },
-            "graceful-fs": {
-              "version": "4.1.11",
-              "bundled": true
-            },
-            "has-ansi": {
-              "version": "2.0.0",
-              "bundled": true,
-              "requires": {
-                "ansi-regex": "^2.0.0"
-              }
-            },
-            "home-or-tmp": {
-              "version": "2.0.0",
-              "bundled": true,
-              "requires": {
-                "os-homedir": "^1.0.0",
-                "os-tmpdir": "^1.0.1"
-              }
-            },
-            "inflight": {
-              "version": "1.0.6",
-              "bundled": true,
-              "requires": {
-                "once": "^1.3.0",
-                "wrappy": "1"
-              }
-            },
-            "inherits": {
-              "version": "2.0.3",
-              "bundled": true
-            },
-            "invariant": {
-              "version": "2.2.4",
-              "bundled": true,
-              "requires": {
-                "loose-envify": "^1.0.0"
-              }
-            },
-            "is-binary-path": {
-              "version": "1.0.1",
-              "bundled": true,
-              "optional": true,
-              "requires": {
-                "binary-extensions": "^1.0.0"
-              }
+              "dependencies": {
+                "abbrev": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "optional": true
+                },
+                "ansi-regex": {
+                  "version": "2.1.1",
+                  "bundled": true
+                },
+                "aproba": {
+                  "version": "1.2.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "are-we-there-yet": {
+                  "version": "1.1.4",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "delegates": "^1.0.0",
+                    "readable-stream": "^2.0.6"
+                  }
+                },
+                "balanced-match": {
+                  "version": "1.0.0",
+                  "bundled": true
+                },
+                "brace-expansion": {
+                  "version": "1.1.11",
+                  "bundled": true,
+                  "requires": {
+                    "balanced-match": "^1.0.0",
+                    "concat-map": "0.0.1"
+                  }
+                },
+                "chownr": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "optional": true
+                },
+                "code-point-at": {
+                  "version": "1.1.0",
+                  "bundled": true
+                },
+                "concat-map": {
+                  "version": "0.0.1",
+                  "bundled": true
+                },
+                "console-control-strings": {
+                  "version": "1.1.0",
+                  "bundled": true
+                },
+                "core-util-is": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "optional": true
+                },
+                "debug": {
+                  "version": "2.6.9",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "ms": "2.0.0"
+                  }
+                },
+                "deep-extend": {
+                  "version": "0.5.1",
+                  "bundled": true,
+                  "optional": true
+                },
+                "delegates": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "detect-libc": {
+                  "version": "1.0.3",
+                  "bundled": true,
+                  "optional": true
+                },
+                "fs-minipass": {
+                  "version": "1.2.5",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.2.1"
+                  }
+                },
+                "fs.realpath": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "gauge": {
+                  "version": "2.7.4",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "aproba": "^1.0.3",
+                    "console-control-strings": "^1.0.0",
+                    "has-unicode": "^2.0.0",
+                    "object-assign": "^4.1.0",
+                    "signal-exit": "^3.0.0",
+                    "string-width": "^1.0.1",
+                    "strip-ansi": "^3.0.1",
+                    "wide-align": "^1.1.0"
+                  }
+                },
+                "glob": {
+                  "version": "7.1.2",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "fs.realpath": "^1.0.0",
+                    "inflight": "^1.0.4",
+                    "inherits": "2",
+                    "minimatch": "^3.0.4",
+                    "once": "^1.3.0",
+                    "path-is-absolute": "^1.0.0"
+                  }
+                },
+                "has-unicode": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "optional": true
+                },
+                "iconv-lite": {
+                  "version": "0.4.21",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "safer-buffer": "^2.1.0"
+                  }
+                },
+                "ignore-walk": {
+                  "version": "3.0.1",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "minimatch": "^3.0.4"
+                  }
+                },
+                "inflight": {
+                  "version": "1.0.6",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "once": "^1.3.0",
+                    "wrappy": "1"
+                  }
+                },
+                "inherits": {
+                  "version": "2.0.3",
+                  "bundled": true
+                },
+                "ini": {
+                  "version": "1.3.5",
+                  "bundled": true,
+                  "optional": true
+                },
+                "is-fullwidth-code-point": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "requires": {
+                    "number-is-nan": "^1.0.0"
+                  }
+                },
+                "isarray": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "minimatch": {
+                  "version": "3.0.4",
+                  "bundled": true,
+                  "requires": {
+                    "brace-expansion": "^1.1.7"
+                  }
+                },
+                "minimist": {
+                  "version": "0.0.8",
+                  "bundled": true
+                },
+                "minipass": {
+                  "version": "2.2.4",
+                  "bundled": true,
+                  "requires": {
+                    "safe-buffer": "^5.1.1",
+                    "yallist": "^3.0.0"
+                  }
+                },
+                "minizlib": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.2.1"
+                  }
+                },
+                "mkdirp": {
+                  "version": "0.5.1",
+                  "bundled": true,
+                  "requires": {
+                    "minimist": "0.0.8"
+                  }
+                },
+                "ms": {
+                  "version": "2.0.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "needle": {
+                  "version": "2.2.0",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "debug": "^2.1.2",
+                    "iconv-lite": "^0.4.4",
+                    "sax": "^1.2.4"
+                  }
+                },
+                "node-pre-gyp": {
+                  "version": "0.10.0",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "detect-libc": "^1.0.2",
+                    "mkdirp": "^0.5.1",
+                    "needle": "^2.2.0",
+                    "nopt": "^4.0.1",
+                    "npm-packlist": "^1.1.6",
+                    "npmlog": "^4.0.2",
+                    "rc": "^1.1.7",
+                    "rimraf": "^2.6.1",
+                    "semver": "^5.3.0",
+                    "tar": "^4"
+                  }
+                },
+                "nopt": {
+                  "version": "4.0.1",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "abbrev": "1",
+                    "osenv": "^0.1.4"
+                  }
+                },
+                "npm-bundled": {
+                  "version": "1.0.3",
+                  "bundled": true,
+                  "optional": true
+                },
+                "npm-packlist": {
+                  "version": "1.1.10",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "ignore-walk": "^3.0.1",
+                    "npm-bundled": "^1.0.1"
+                  }
+                },
+                "npmlog": {
+                  "version": "4.1.2",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "are-we-there-yet": "~1.1.2",
+                    "console-control-strings": "~1.1.0",
+                    "gauge": "~2.7.3",
+                    "set-blocking": "~2.0.0"
+                  }
+                },
+                "number-is-nan": {
+                  "version": "1.0.1",
+                  "bundled": true
+                },
+                "object-assign": {
+                  "version": "4.1.1",
+                  "bundled": true,
+                  "optional": true
+                },
+                "once": {
+                  "version": "1.4.0",
+                  "bundled": true,
+                  "requires": {
+                    "wrappy": "1"
+                  }
+                },
+                "os-homedir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "optional": true
+                },
+                "os-tmpdir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "optional": true
+                },
+                "osenv": {
+                  "version": "0.1.5",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "os-homedir": "^1.0.0",
+                    "os-tmpdir": "^1.0.0"
+                  }
+                },
+                "path-is-absolute": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "optional": true
+                },
+                "process-nextick-args": {
+                  "version": "2.0.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "rc": {
+                  "version": "1.2.7",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "deep-extend": "^0.5.1",
+                    "ini": "~1.3.0",
+                    "minimist": "^1.2.0",
+                    "strip-json-comments": "~2.0.1"
+                  },
+                  "dependencies": {
+                    "minimist": {
+                      "version": "1.2.0",
+                      "bundled": true,
+                      "optional": true
+                    }
+                  }
+                },
+                "readable-stream": {
+                  "version": "2.3.6",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "core-util-is": "~1.0.0",
+                    "inherits": "~2.0.3",
+                    "isarray": "~1.0.0",
+                    "process-nextick-args": "~2.0.0",
+                    "safe-buffer": "~5.1.1",
+                    "string_decoder": "~1.1.1",
+                    "util-deprecate": "~1.0.1"
+                  }
+                },
+                "rimraf": {
+                  "version": "2.6.2",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "glob": "^7.0.5"
+                  }
+                },
+                "safe-buffer": {
+                  "version": "5.1.1",
+                  "bundled": true
+                },
+                "safer-buffer": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "optional": true
+                },
+                "sax": {
+                  "version": "1.2.4",
+                  "bundled": true,
+                  "optional": true
+                },
+                "semver": {
+                  "version": "5.5.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "set-blocking": {
+                  "version": "2.0.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "signal-exit": {
+                  "version": "3.0.2",
+                  "bundled": true,
+                  "optional": true
+                },
+                "string-width": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "requires": {
+                    "code-point-at": "^1.0.0",
+                    "is-fullwidth-code-point": "^1.0.0",
+                    "strip-ansi": "^3.0.0"
+                  }
+                },
+                "string_decoder": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "~5.1.0"
+                  }
+                },
+                "strip-ansi": {
+                  "version": "3.0.1",
+                  "bundled": true,
+                  "requires": {
+                    "ansi-regex": "^2.0.0"
+                  }
+                },
+                "strip-json-comments": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "optional": true
+                },
+                "tar": {
+                  "version": "4.4.1",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "chownr": "^1.0.1",
+                    "fs-minipass": "^1.2.5",
+                    "minipass": "^2.2.4",
+                    "minizlib": "^1.1.0",
+                    "mkdirp": "^0.5.0",
+                    "safe-buffer": "^5.1.1",
+                    "yallist": "^3.0.2"
+                  }
+                },
+                "util-deprecate": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "optional": true
+                },
+                "wide-align": {
+                  "version": "1.1.2",
+                  "bundled": true,
+                  "optional": true,
+                  "requires": {
+                    "string-width": "^1.0.2"
+                  }
+                },
+                "wrappy": {
+                  "version": "1.0.2",
+                  "bundled": true
+                },
+                "yallist": {
+                  "version": "3.0.2",
+                  "bundled": true
+                }
+              }
+            },
+            "glob": {
+              "version": "7.1.2",
+              "bundled": true,
+              "requires": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.0.4",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+              }
+            },
+            "glob-base": {
+              "version": "0.3.0",
+              "bundled": true,
+              "optional": true,
+              "requires": {
+                "glob-parent": "^2.0.0",
+                "is-glob": "^2.0.0"
+              }
+            },
+            "glob-parent": {
+              "version": "2.0.0",
+              "bundled": true,
+              "requires": {
+                "is-glob": "^2.0.0"
+              }
+            },
+            "globals": {
+              "version": "9.18.0",
+              "bundled": true
+            },
+            "graceful-fs": {
+              "version": "4.1.11",
+              "bundled": true
+            },
+            "has-ansi": {
+              "version": "2.0.0",
+              "bundled": true,
+              "requires": {
+                "ansi-regex": "^2.0.0"
+              }
+            },
+            "home-or-tmp": {
+              "version": "2.0.0",
+              "bundled": true,
+              "requires": {
+                "os-homedir": "^1.0.0",
+                "os-tmpdir": "^1.0.1"
+              }
+            },
+            "inflight": {
+              "version": "1.0.6",
+              "bundled": true,
+              "requires": {
+                "once": "^1.3.0",
+                "wrappy": "1"
+              }
+            },
+            "inherits": {
+              "version": "2.0.3",
+              "bundled": true
+            },
+            "invariant": {
+              "version": "2.2.4",
+              "bundled": true,
+              "requires": {
+                "loose-envify": "^1.0.0"
+              }
+            },
+            "is-binary-path": {
+              "version": "1.0.1",
+              "bundled": true,
+              "optional": true,
+              "requires": {
+                "binary-extensions": "^1.0.0"
+              }
             },
             "is-buffer": {
               "version": "1.1.6",
@@ -7523,7 +8165,18 @@
                 "kind-of": "^6.0.0",
                 "math-random": "^1.0.1"
               },
-              "dependencies": {}
+              "dependencies": {
+                "is-number": {
+                  "version": "4.0.0",
+                  "bundled": true,
+                  "optional": true
+                },
+                "kind-of": {
+                  "version": "6.0.2",
+                  "bundled": true,
+                  "optional": true
+                }
+              }
             },
             "readable-stream": {
               "version": "2.3.6",
@@ -7594,7 +8247,12 @@
               "requires": {
                 "jsesc": "~0.5.0"
               },
-              "dependencies": {}
+              "dependencies": {
+                "jsesc": {
+                  "version": "0.5.0",
+                  "bundled": true
+                }
+              }
             },
             "remove-trailing-separator": {
               "version": "1.1.0",
@@ -7728,6 +8386,13 @@
             "buffer-indexof": "^1.0.0"
           }
         },
+        "doctrine": {
+          "version": "2.1.0",
+          "bundled": true,
+          "requires": {
+            "esutils": "^2.0.2"
+          }
+        },
         "domain-browser": {
           "version": "1.2.0",
           "bundled": true
@@ -7735,21 +8400,20 @@
         "ecc-jsbn": {
           "version": "0.1.2",
           "bundled": true,
-          "optional": true,
           "requires": {
             "jsbn": "~0.1.0",
             "safer-buffer": "^2.1.0"
           }
         },
         "editorconfig": {
-          "version": "0.15.0",
+          "version": "0.15.2",
           "bundled": true,
           "requires": {
-            "@types/commander": "^2.11.0",
-            "@types/semver": "^5.4.0",
-            "commander": "^2.11.0",
-            "lru-cache": "^4.1.1",
-            "semver": "^5.4.1",
+            "@types/node": "^10.11.7",
+            "@types/semver": "^5.5.0",
+            "commander": "^2.19.0",
+            "lru-cache": "^4.1.3",
+            "semver": "^5.6.0",
             "sigmund": "^1.0.1"
           }
         },
@@ -7758,7 +8422,7 @@
           "bundled": true
         },
         "electron-to-chromium": {
-          "version": "1.3.72",
+          "version": "1.3.82",
           "bundled": true
         },
         "elliptic": {
@@ -7874,46 +8538,247 @@
             "event-emitter": "~0.3.5"
           }
         },
-        "es6-symbol": {
-          "version": "3.1.1",
+        "es6-symbol": {
+          "version": "3.1.1",
+          "bundled": true,
+          "requires": {
+            "d": "1",
+            "es5-ext": "~0.10.14"
+          }
+        },
+        "es6-weak-map": {
+          "version": "2.0.2",
+          "bundled": true,
+          "requires": {
+            "d": "1",
+            "es5-ext": "^0.10.14",
+            "es6-iterator": "^2.0.1",
+            "es6-symbol": "^3.1.1"
+          }
+        },
+        "escape-html": {
+          "version": "1.0.3",
+          "bundled": true
+        },
+        "escape-string-regexp": {
+          "version": "1.0.5",
+          "bundled": true
+        },
+        "escope": {
+          "version": "3.6.0",
+          "bundled": true,
+          "requires": {
+            "es6-map": "^0.1.3",
+            "es6-weak-map": "^2.0.1",
+            "esrecurse": "^4.1.0",
+            "estraverse": "^4.1.1"
+          }
+        },
+        "eslint": {
+          "version": "5.7.0",
+          "bundled": true,
+          "requires": {
+            "@babel/code-frame": "^7.0.0",
+            "ajv": "^6.5.3",
+            "chalk": "^2.1.0",
+            "cross-spawn": "^6.0.5",
+            "debug": "^4.0.1",
+            "doctrine": "^2.1.0",
+            "eslint-scope": "^4.0.0",
+            "eslint-utils": "^1.3.1",
+            "eslint-visitor-keys": "^1.0.0",
+            "espree": "^4.0.0",
+            "esquery": "^1.0.1",
+            "esutils": "^2.0.2",
+            "file-entry-cache": "^2.0.0",
+            "functional-red-black-tree": "^1.0.1",
+            "glob": "^7.1.2",
+            "globals": "^11.7.0",
+            "ignore": "^4.0.6",
+            "imurmurhash": "^0.1.4",
+            "inquirer": "^6.1.0",
+            "is-resolvable": "^1.1.0",
+            "js-yaml": "^3.12.0",
+            "json-stable-stringify-without-jsonify": "^1.0.1",
+            "levn": "^0.3.0",
+            "lodash": "^4.17.5",
+            "minimatch": "^3.0.4",
+            "mkdirp": "^0.5.1",
+            "natural-compare": "^1.4.0",
+            "optionator": "^0.8.2",
+            "path-is-inside": "^1.0.2",
+            "pluralize": "^7.0.0",
+            "progress": "^2.0.0",
+            "regexpp": "^2.0.1",
+            "require-uncached": "^1.0.3",
+            "semver": "^5.5.1",
+            "strip-ansi": "^4.0.0",
+            "strip-json-comments": "^2.0.1",
+            "table": "^5.0.2",
+            "text-table": "^0.2.0"
+          },
+          "dependencies": {
+            "ansi-escapes": {
+              "version": "3.1.0",
+              "bundled": true
+            },
+            "ansi-regex": {
+              "version": "3.0.0",
+              "bundled": true
+            },
+            "ansi-styles": {
+              "version": "3.2.1",
+              "bundled": true,
+              "requires": {
+                "color-convert": "^1.9.0"
+              }
+            },
+            "chalk": {
+              "version": "2.4.1",
+              "bundled": true,
+              "requires": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+              }
+            },
+            "chardet": {
+              "version": "0.7.0",
+              "bundled": true
+            },
+            "cross-spawn": {
+              "version": "6.0.5",
+              "bundled": true,
+              "requires": {
+                "nice-try": "^1.0.4",
+                "path-key": "^2.0.1",
+                "semver": "^5.5.0",
+                "shebang-command": "^1.2.0",
+                "which": "^1.2.9"
+              }
+            },
+            "debug": {
+              "version": "4.1.0",
+              "bundled": true,
+              "requires": {
+                "ms": "^2.1.1"
+              }
+            },
+            "eslint-scope": {
+              "version": "4.0.0",
+              "bundled": true,
+              "requires": {
+                "esrecurse": "^4.1.0",
+                "estraverse": "^4.1.1"
+              }
+            },
+            "esprima": {
+              "version": "4.0.1",
+              "bundled": true
+            },
+            "external-editor": {
+              "version": "3.0.3",
+              "bundled": true,
+              "requires": {
+                "chardet": "^0.7.0",
+                "iconv-lite": "^0.4.24",
+                "tmp": "^0.0.33"
+              }
+            },
+            "globals": {
+              "version": "11.8.0",
+              "bundled": true
+            },
+            "inquirer": {
+              "version": "6.2.0",
+              "bundled": true,
+              "requires": {
+                "ansi-escapes": "^3.0.0",
+                "chalk": "^2.0.0",
+                "cli-cursor": "^2.1.0",
+                "cli-width": "^2.0.0",
+                "external-editor": "^3.0.0",
+                "figures": "^2.0.0",
+                "lodash": "^4.17.10",
+                "mute-stream": "0.0.7",
+                "run-async": "^2.2.0",
+                "rxjs": "^6.1.0",
+                "string-width": "^2.1.0",
+                "strip-ansi": "^4.0.0",
+                "through": "^2.3.6"
+              }
+            },
+            "js-yaml": {
+              "version": "3.12.0",
+              "bundled": true,
+              "requires": {
+                "argparse": "^1.0.7",
+                "esprima": "^4.0.0"
+              }
+            },
+            "ms": {
+              "version": "2.1.1",
+              "bundled": true
+            },
+            "strip-ansi": {
+              "version": "4.0.0",
+              "bundled": true,
+              "requires": {
+                "ansi-regex": "^3.0.0"
+              }
+            },
+            "supports-color": {
+              "version": "5.5.0",
+              "bundled": true,
+              "requires": {
+                "has-flag": "^3.0.0"
+              }
+            }
+          }
+        },
+        "eslint-plugin-vue": {
+          "version": "4.7.1",
           "bundled": true,
           "requires": {
-            "d": "1",
-            "es5-ext": "~0.10.14"
+            "vue-eslint-parser": "^2.0.3"
           }
         },
-        "es6-weak-map": {
-          "version": "2.0.2",
+        "eslint-scope": {
+          "version": "3.7.1",
           "bundled": true,
           "requires": {
-            "d": "1",
-            "es5-ext": "^0.10.14",
-            "es6-iterator": "^2.0.1",
-            "es6-symbol": "^3.1.1"
+            "esrecurse": "^4.1.0",
+            "estraverse": "^4.1.1"
           }
         },
-        "escape-html": {
-          "version": "1.0.3",
+        "eslint-utils": {
+          "version": "1.3.1",
           "bundled": true
         },
-        "escape-string-regexp": {
-          "version": "1.0.5",
+        "eslint-visitor-keys": {
+          "version": "1.0.0",
           "bundled": true
         },
-        "escope": {
-          "version": "3.6.0",
+        "espree": {
+          "version": "4.1.0",
           "bundled": true,
           "requires": {
-            "es6-map": "^0.1.3",
-            "es6-weak-map": "^2.0.1",
-            "esrecurse": "^4.1.0",
-            "estraverse": "^4.1.1"
+            "acorn": "^6.0.2",
+            "acorn-jsx": "^5.0.0",
+            "eslint-visitor-keys": "^1.0.0"
           }
         },
         "esprima": {
           "version": "2.7.3",
           "bundled": true
         },
+        "esquery": {
+          "version": "1.0.1",
+          "bundled": true,
+          "requires": {
+            "estraverse": "^4.0.0"
+          }
+        },
         "esrecurse": {
           "version": "4.2.1",
           "bundled": true,
@@ -8048,12 +8913,12 @@
           }
         },
         "express": {
-          "version": "4.16.3",
+          "version": "4.16.4",
           "bundled": true,
           "requires": {
             "accepts": "~1.3.5",
             "array-flatten": "1.1.1",
-            "body-parser": "1.18.2",
+            "body-parser": "1.18.3",
             "content-disposition": "0.5.2",
             "content-type": "~1.0.4",
             "cookie": "0.3.1",
@@ -8070,10 +8935,10 @@
             "on-finished": "~2.3.0",
             "parseurl": "~1.3.2",
             "path-to-regexp": "0.1.7",
-            "proxy-addr": "~2.0.3",
-            "qs": "6.5.1",
+            "proxy-addr": "~2.0.4",
+            "qs": "6.5.2",
             "range-parser": "~1.2.0",
-            "safe-buffer": "5.1.1",
+            "safe-buffer": "5.1.2",
             "send": "0.16.2",
             "serve-static": "1.13.2",
             "setprototypeof": "1.1.0",
@@ -8086,14 +8951,6 @@
             "array-flatten": {
               "version": "1.1.1",
               "bundled": true
-            },
-            "qs": {
-              "version": "6.5.1",
-              "bundled": true
-            },
-            "safe-buffer": {
-              "version": "5.1.1",
-              "bundled": true
             }
           }
         },
@@ -8195,13 +9052,17 @@
           "bundled": true
         },
         "fast-deep-equal": {
-          "version": "1.1.0",
+          "version": "2.0.1",
           "bundled": true
         },
         "fast-json-stable-stringify": {
           "version": "2.0.0",
           "bundled": true
         },
+        "fast-levenshtein": {
+          "version": "2.0.6",
+          "bundled": true
+        },
         "fastparse": {
           "version": "1.1.1",
           "bundled": true
@@ -8220,6 +9081,14 @@
             "escape-string-regexp": "^1.0.5"
           }
         },
+        "file-entry-cache": {
+          "version": "2.0.0",
+          "bundled": true,
+          "requires": {
+            "flat-cache": "^1.2.1",
+            "object-assign": "^4.0.1"
+          }
+        },
         "file-loader": {
           "version": "0.9.0",
           "bundled": true,
@@ -8291,12 +9160,22 @@
             "locate-path": "^2.0.0"
           }
         },
+        "flat-cache": {
+          "version": "1.3.0",
+          "bundled": true,
+          "requires": {
+            "circular-json": "^0.3.1",
+            "del": "^2.0.2",
+            "graceful-fs": "^4.1.2",
+            "write": "^0.2.1"
+          }
+        },
         "flatten": {
           "version": "1.0.2",
           "bundled": true
         },
         "follow-redirects": {
-          "version": "1.5.8",
+          "version": "1.5.9",
           "bundled": true,
           "requires": {
             "debug": "=3.1.0"
@@ -8327,21 +9206,12 @@
           "bundled": true
         },
         "form-data": {
-          "version": "2.3.2",
+          "version": "2.3.3",
           "bundled": true,
           "requires": {
             "asynckit": "^0.4.0",
-            "combined-stream": "1.0.6",
+            "combined-stream": "^1.0.6",
             "mime-types": "^2.1.12"
-          },
-          "dependencies": {
-            "combined-stream": {
-              "version": "1.0.6",
-              "bundled": true,
-              "requires": {
-                "delayed-stream": "~1.0.0"
-              }
-            }
           }
         },
         "forwarded": {
@@ -8838,6 +9708,10 @@
           "version": "1.1.1",
           "bundled": true
         },
+        "functional-red-black-tree": {
+          "version": "1.0.1",
+          "bundled": true
+        },
         "gauge": {
           "version": "2.7.4",
           "bundled": true,
@@ -8962,10 +9836,11 @@
           "bundled": true
         },
         "globby": {
-          "version": "6.1.0",
+          "version": "5.0.0",
           "bundled": true,
           "requires": {
             "array-union": "^1.0.1",
+            "arrify": "^1.0.0",
             "glob": "^7.0.3",
             "object-assign": "^4.0.1",
             "pify": "^2.0.0",
@@ -9000,11 +9875,31 @@
           "bundled": true
         },
         "har-validator": {
-          "version": "5.0.3",
+          "version": "5.1.0",
           "bundled": true,
           "requires": {
-            "ajv": "^5.1.0",
+            "ajv": "^5.3.0",
             "har-schema": "^2.0.0"
+          },
+          "dependencies": {
+            "ajv": {
+              "version": "5.5.2",
+              "bundled": true,
+              "requires": {
+                "co": "^4.6.0",
+                "fast-deep-equal": "^1.0.0",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.3.0"
+              }
+            },
+            "fast-deep-equal": {
+              "version": "1.1.0",
+              "bundled": true
+            },
+            "json-schema-traverse": {
+              "version": "0.3.1",
+              "bundled": true
+            }
           }
         },
         "has": {
@@ -9022,7 +9917,7 @@
           }
         },
         "has-flag": {
-          "version": "1.0.0",
+          "version": "3.0.0",
           "bundled": true
         },
         "has-symbols": {
@@ -9116,7 +10011,7 @@
           }
         },
         "html-comment-regex": {
-          "version": "1.1.1",
+          "version": "1.1.2",
           "bundled": true
         },
         "html-entities": {
@@ -9138,7 +10033,7 @@
           }
         },
         "http-parser-js": {
-          "version": "0.4.13",
+          "version": "0.5.0",
           "bundled": true
         },
         "http-proxy": {
@@ -9276,6 +10171,10 @@
           "version": "1.1.12",
           "bundled": true
         },
+        "ignore": {
+          "version": "4.0.6",
+          "bundled": true
+        },
         "import-local": {
           "version": "1.0.0",
           "bundled": true,
@@ -9284,6 +10183,10 @@
             "resolve-cwd": "^2.0.0"
           }
         },
+        "imurmurhash": {
+          "version": "0.1.4",
+          "bundled": true
+        },
         "in-publish": {
           "version": "2.0.0",
           "bundled": true
@@ -9554,6 +10457,10 @@
             "has": "^1.0.1"
           }
         },
+        "is-resolvable": {
+          "version": "1.1.0",
+          "bundled": true
+        },
         "is-stream": {
           "version": "1.1.0",
           "bundled": true
@@ -9609,7 +10516,7 @@
           "bundled": true
         },
         "js-beautify": {
-          "version": "1.8.6",
+          "version": "1.8.8",
           "bundled": true,
           "requires": {
             "config-chain": "~1.1.5",
@@ -9642,8 +10549,7 @@
         },
         "jsbn": {
           "version": "0.1.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "jsesc": {
           "version": "1.3.0",
@@ -9659,7 +10565,11 @@
           "bundled": true
         },
         "json-schema-traverse": {
-          "version": "0.3.1",
+          "version": "0.4.1",
+          "bundled": true
+        },
+        "json-stable-stringify-without-jsonify": {
+          "version": "1.0.1",
           "bundled": true
         },
         "json-stringify-safe": {
@@ -9703,6 +10613,14 @@
             "invert-kv": "^1.0.0"
           }
         },
+        "levn": {
+          "version": "0.3.0",
+          "bundled": true,
+          "requires": {
+            "prelude-ls": "~1.1.2",
+            "type-check": "~0.3.2"
+          }
+        },
         "load-json-file": {
           "version": "1.1.0",
           "bundled": true,
@@ -9876,11 +10794,12 @@
           "bundled": true
         },
         "md5.js": {
-          "version": "1.3.4",
+          "version": "1.3.5",
           "bundled": true,
           "requires": {
             "hash-base": "^3.0.0",
-            "inherits": "^2.0.1"
+            "inherits": "^2.0.1",
+            "safe-buffer": "^5.1.2"
           }
         },
         "media-typer": {
@@ -9958,14 +10877,14 @@
           "bundled": true
         },
         "mime-db": {
-          "version": "1.36.0",
+          "version": "1.37.0",
           "bundled": true
         },
         "mime-types": {
-          "version": "2.1.20",
+          "version": "2.1.21",
           "bundled": true,
           "requires": {
-            "mime-db": "~1.36.0"
+            "mime-db": "~1.37.0"
           }
         },
         "mimic-fn": {
@@ -10076,18 +10995,26 @@
             "to-regex": "^3.0.1"
           }
         },
+        "natural-compare": {
+          "version": "1.4.0",
+          "bundled": true
+        },
         "negotiator": {
           "version": "0.6.1",
           "bundled": true
         },
         "neo-async": {
-          "version": "2.5.2",
+          "version": "2.6.0",
           "bundled": true
         },
         "next-tick": {
           "version": "1.0.0",
           "bundled": true
         },
+        "nice-try": {
+          "version": "1.0.5",
+          "bundled": true
+        },
         "node-fetch": {
           "version": "1.6.3",
           "bundled": true,
@@ -10151,10 +11078,16 @@
             "url": "^0.11.0",
             "util": "^0.10.3",
             "vm-browserify": "0.0.4"
+          },
+          "dependencies": {
+            "punycode": {
+              "version": "1.4.1",
+              "bundled": true
+            }
           }
         },
         "node-sass": {
-          "version": "4.9.3",
+          "version": "4.9.4",
           "bundled": true,
           "requires": {
             "async-foreach": "^0.1.3",
@@ -10172,7 +11105,7 @@
             "nan": "^2.10.0",
             "node-gyp": "^3.8.0",
             "npmlog": "^4.0.0",
-            "request": "2.87.0",
+            "request": "^2.88.0",
             "sass-graph": "^2.2.4",
             "stdout-stream": "^1.4.0",
             "true-case-path": "^1.0.2"
@@ -10252,7 +11185,7 @@
           "bundled": true
         },
         "oauth-sign": {
-          "version": "0.8.2",
+          "version": "0.9.0",
           "bundled": true
         },
         "object-assign": {
@@ -10368,6 +11301,18 @@
             "pinkie-promise": "^2.0.0"
           }
         },
+        "optionator": {
+          "version": "0.8.2",
+          "bundled": true,
+          "requires": {
+            "deep-is": "~0.1.3",
+            "fast-levenshtein": "~2.0.4",
+            "levn": "~0.3.0",
+            "prelude-ls": "~1.1.2",
+            "type-check": "~0.3.2",
+            "wordwrap": "~1.0.0"
+          }
+        },
         "original": {
           "version": "1.0.2",
           "bundled": true,
@@ -10565,12 +11510,16 @@
             "find-up": "^2.1.0"
           }
         },
+        "pluralize": {
+          "version": "7.0.0",
+          "bundled": true
+        },
         "popper.js": {
           "version": "1.14.4",
           "bundled": true
         },
         "portfinder": {
-          "version": "1.0.17",
+          "version": "1.0.19",
           "bundled": true,
           "requires": {
             "async": "^1.5.2",
@@ -10598,6 +11547,10 @@
             "supports-color": "^3.2.3"
           },
           "dependencies": {
+            "has-flag": {
+              "version": "1.0.0",
+              "bundled": true
+            },
             "supports-color": {
               "version": "3.2.3",
               "bundled": true,
@@ -10803,10 +11756,6 @@
                 "supports-color": "^5.3.0"
               }
             },
-            "has-flag": {
-              "version": "3.0.0",
-              "bundled": true
-            },
             "postcss": {
               "version": "6.0.23",
               "bundled": true,
@@ -10862,10 +11811,6 @@
                 "regexpu-core": "^1.0.0"
               }
             },
-            "has-flag": {
-              "version": "3.0.0",
-              "bundled": true
-            },
             "postcss": {
               "version": "6.0.23",
               "bundled": true,
@@ -10930,10 +11875,6 @@
                 "regexpu-core": "^1.0.0"
               }
             },
-            "has-flag": {
-              "version": "3.0.0",
-              "bundled": true
-            },
             "postcss": {
               "version": "6.0.23",
               "bundled": true,
@@ -10989,10 +11930,6 @@
                 "supports-color": "^5.3.0"
               }
             },
-            "has-flag": {
-              "version": "3.0.0",
-              "bundled": true
-            },
             "postcss": {
               "version": "6.0.23",
               "bundled": true,
@@ -11093,7 +12030,7 @@
           }
         },
         "postcss-value-parser": {
-          "version": "3.3.0",
+          "version": "3.3.1",
           "bundled": true
         },
         "postcss-zindex": {
@@ -11105,6 +12042,10 @@
             "uniqs": "^2.0.0"
           }
         },
+        "prelude-ls": {
+          "version": "1.1.2",
+          "bundled": true
+        },
         "prepend-http": {
           "version": "1.0.4",
           "bundled": true
@@ -11125,6 +12066,10 @@
           "version": "2.0.0",
           "bundled": true
         },
+        "progress": {
+          "version": "2.0.1",
+          "bundled": true
+        },
         "proto-list": {
           "version": "1.2.4",
           "bundled": true
@@ -11145,19 +12090,24 @@
           "version": "1.0.2",
           "bundled": true
         },
+        "psl": {
+          "version": "1.1.29",
+          "bundled": true
+        },
         "public-encrypt": {
-          "version": "4.0.2",
+          "version": "4.0.3",
           "bundled": true,
           "requires": {
             "bn.js": "^4.1.0",
             "browserify-rsa": "^4.0.0",
             "create-hash": "^1.1.0",
             "parse-asn1": "^5.0.0",
-            "randombytes": "^2.0.1"
+            "randombytes": "^2.0.1",
+            "safe-buffer": "^5.1.2"
           }
         },
         "punycode": {
-          "version": "1.4.1",
+          "version": "2.1.1",
           "bundled": true
         },
         "q": {
@@ -11185,11 +12135,11 @@
           "bundled": true
         },
         "querystringify": {
-          "version": "2.0.0",
+          "version": "2.1.0",
           "bundled": true
         },
         "randomatic": {
-          "version": "3.1.0",
+          "version": "3.1.1",
           "bundled": true,
           "requires": {
             "is-number": "^4.0.0",
@@ -11223,36 +12173,21 @@
           "bundled": true
         },
         "raw-body": {
-          "version": "2.3.2",
+          "version": "2.3.3",
           "bundled": true,
           "requires": {
             "bytes": "3.0.0",
-            "http-errors": "1.6.2",
-            "iconv-lite": "0.4.19",
+            "http-errors": "1.6.3",
+            "iconv-lite": "0.4.23",
             "unpipe": "1.0.0"
           },
           "dependencies": {
-            "depd": {
-              "version": "1.1.1",
-              "bundled": true
-            },
-            "http-errors": {
-              "version": "1.6.2",
-              "bundled": true,
-              "requires": {
-                "depd": "1.1.1",
-                "inherits": "2.0.3",
-                "setprototypeof": "1.0.3",
-                "statuses": ">= 1.3.1 < 2"
-              }
-            },
-            "iconv-lite": {
-              "version": "0.4.19",
-              "bundled": true
-            },
-            "setprototypeof": {
-              "version": "1.0.3",
-              "bundled": true
+            "iconv-lite": {
+              "version": "0.4.23",
+              "bundled": true,
+              "requires": {
+                "safer-buffer": ">= 2.1.2 < 3"
+              }
             }
           }
         },
@@ -11380,6 +12315,10 @@
             "safe-regex": "^1.1.0"
           }
         },
+        "regexpp": {
+          "version": "2.0.1",
+          "bundled": true
+        },
         "regexpu-core": {
           "version": "2.0.0",
           "bundled": true,
@@ -11426,29 +12365,29 @@
           }
         },
         "request": {
-          "version": "2.87.0",
+          "version": "2.88.0",
           "bundled": true,
           "requires": {
             "aws-sign2": "~0.7.0",
-            "aws4": "^1.6.0",
+            "aws4": "^1.8.0",
             "caseless": "~0.12.0",
-            "combined-stream": "~1.0.5",
-            "extend": "~3.0.1",
+            "combined-stream": "~1.0.6",
+            "extend": "~3.0.2",
             "forever-agent": "~0.6.1",
-            "form-data": "~2.3.1",
-            "har-validator": "~5.0.3",
+            "form-data": "~2.3.2",
+            "har-validator": "~5.1.0",
             "http-signature": "~1.2.0",
             "is-typedarray": "~1.0.0",
             "isstream": "~0.1.2",
             "json-stringify-safe": "~5.0.1",
-            "mime-types": "~2.1.17",
-            "oauth-sign": "~0.8.2",
+            "mime-types": "~2.1.19",
+            "oauth-sign": "~0.9.0",
             "performance-now": "^2.1.0",
-            "qs": "~6.5.1",
-            "safe-buffer": "^5.1.1",
-            "tough-cookie": "~2.3.3",
+            "qs": "~6.5.2",
+            "safe-buffer": "^5.1.2",
+            "tough-cookie": "~2.4.3",
             "tunnel-agent": "^0.6.0",
-            "uuid": "^3.1.0"
+            "uuid": "^3.3.2"
           }
         },
         "require-directory": {
@@ -11463,6 +12402,14 @@
           "version": "1.0.1",
           "bundled": true
         },
+        "require-uncached": {
+          "version": "1.0.3",
+          "bundled": true,
+          "requires": {
+            "caller-path": "^0.1.0",
+            "resolve-from": "^1.0.0"
+          }
+        },
         "requires-port": {
           "version": "1.0.0",
           "bundled": true
@@ -11479,10 +12426,16 @@
           "bundled": true,
           "requires": {
             "resolve-from": "^3.0.0"
+          },
+          "dependencies": {
+            "resolve-from": {
+              "version": "3.0.0",
+              "bundled": true
+            }
           }
         },
         "resolve-from": {
-          "version": "3.0.0",
+          "version": "1.0.1",
           "bundled": true
         },
         "resolve-url": {
@@ -11534,6 +12487,13 @@
           "version": "4.1.0",
           "bundled": true
         },
+        "rxjs": {
+          "version": "6.3.3",
+          "bundled": true,
+          "requires": {
+            "tslib": "^1.9.0"
+          }
+        },
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true
@@ -11579,6 +12539,26 @@
           "bundled": true,
           "requires": {
             "ajv": "^5.0.0"
+          },
+          "dependencies": {
+            "ajv": {
+              "version": "5.5.2",
+              "bundled": true,
+              "requires": {
+                "co": "^4.6.0",
+                "fast-deep-equal": "^1.0.0",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.3.0"
+              }
+            },
+            "fast-deep-equal": {
+              "version": "1.1.0",
+              "bundled": true
+            },
+            "json-schema-traverse": {
+              "version": "0.3.1",
+              "bundled": true
+            }
           }
         },
         "scss-tokenizer": {
@@ -11603,14 +12583,14 @@
           "bundled": true
         },
         "selfsigned": {
-          "version": "1.10.3",
+          "version": "1.10.4",
           "bundled": true,
           "requires": {
             "node-forge": "0.7.5"
           }
         },
         "semver": {
-          "version": "5.5.1",
+          "version": "5.6.0",
           "bundled": true
         },
         "send": {
@@ -11733,6 +12713,13 @@
           "bundled": true,
           "dev": true
         },
+        "slice-ansi": {
+          "version": "1.0.0",
+          "bundled": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0"
+          }
+        },
         "snapdragon": {
           "version": "0.8.2",
           "bundled": true,
@@ -11888,7 +12875,7 @@
           "bundled": true
         },
         "spdx-correct": {
-          "version": "3.0.1",
+          "version": "3.0.2",
           "bundled": true,
           "requires": {
             "spdx-expression-parse": "^3.0.0",
@@ -11896,7 +12883,7 @@
           }
         },
         "spdx-exceptions": {
-          "version": "2.1.0",
+          "version": "2.2.0",
           "bundled": true
         },
         "spdx-expression-parse": {
@@ -11948,7 +12935,7 @@
           "bundled": true
         },
         "sshpk": {
-          "version": "1.14.2",
+          "version": "1.15.1",
           "bundled": true,
           "requires": {
             "asn1": "~0.2.3",
@@ -12066,6 +13053,10 @@
             "get-stdin": "^4.0.1"
           }
         },
+        "strip-json-comments": {
+          "version": "2.0.1",
+          "bundled": true
+        },
         "style-loader": {
           "version": "0.20.3",
           "bundled": true,
@@ -12074,24 +13065,6 @@
             "schema-utils": "^0.4.5"
           },
           "dependencies": {
-            "ajv": {
-              "version": "6.5.4",
-              "bundled": true,
-              "requires": {
-                "fast-deep-equal": "^2.0.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-              }
-            },
-            "fast-deep-equal": {
-              "version": "2.0.1",
-              "bundled": true
-            },
-            "json-schema-traverse": {
-              "version": "0.4.1",
-              "bundled": true
-            },
             "schema-utils": {
               "version": "0.4.7",
               "bundled": true,
@@ -12119,6 +13092,16 @@
             "whet.extend": "~0.9.9"
           }
         },
+        "table": {
+          "version": "5.1.0",
+          "bundled": true,
+          "requires": {
+            "ajv": "^6.5.3",
+            "lodash": "^4.17.10",
+            "slice-ansi": "1.0.0",
+            "string-width": "^2.1.1"
+          }
+        },
         "tapable": {
           "version": "0.2.8",
           "bundled": true
@@ -12132,12 +13115,16 @@
             "inherits": "2"
           }
         },
+        "text-table": {
+          "version": "0.2.0",
+          "bundled": true
+        },
         "through": {
           "version": "2.3.8",
           "bundled": true
         },
         "thunky": {
-          "version": "1.0.2",
+          "version": "1.0.3",
           "bundled": true
         },
         "time-stamp": {
@@ -12201,10 +13188,17 @@
           }
         },
         "tough-cookie": {
-          "version": "2.3.4",
+          "version": "2.4.3",
           "bundled": true,
           "requires": {
+            "psl": "^1.1.24",
             "punycode": "^1.4.1"
+          },
+          "dependencies": {
+            "punycode": {
+              "version": "1.4.1",
+              "bundled": true
+            }
           }
         },
         "trim-newlines": {
@@ -12213,8 +13207,7 @@
         },
         "trim-right": {
           "version": "1.0.1",
-          "bundled": true,
-          "dev": true
+          "bundled": true
         },
         "true-case-path": {
           "version": "1.0.3",
@@ -12223,6 +13216,10 @@
             "glob": "^7.1.2"
           }
         },
+        "tslib": {
+          "version": "1.9.3",
+          "bundled": true
+        },
         "tty-browserify": {
           "version": "0.0.0",
           "bundled": true
@@ -12236,8 +13233,14 @@
         },
         "tweetnacl": {
           "version": "0.14.5",
+          "bundled": true
+        },
+        "type-check": {
+          "version": "0.3.2",
           "bundled": true,
-          "optional": true
+          "requires": {
+            "prelude-ls": "~1.1.2"
+          }
         },
         "type-is": {
           "version": "1.6.16",
@@ -12269,6 +13272,10 @@
                 "wordwrap": "0.0.2"
               }
             },
+            "wordwrap": {
+              "version": "0.0.2",
+              "bundled": true
+            },
             "yargs": {
               "version": "3.10.0",
               "bundled": true,
@@ -12377,12 +13384,6 @@
           "bundled": true,
           "requires": {
             "punycode": "^2.1.0"
-          },
-          "dependencies": {
-            "punycode": {
-              "version": "2.1.1",
-              "bundled": true
-            }
           }
         },
         "urix": {
@@ -12470,6 +13471,56 @@
           "version": "2.5.17",
           "bundled": true
         },
+        "vue-eslint-parser": {
+          "version": "2.0.3",
+          "bundled": true,
+          "requires": {
+            "debug": "^3.1.0",
+            "eslint-scope": "^3.7.1",
+            "eslint-visitor-keys": "^1.0.0",
+            "espree": "^3.5.2",
+            "esquery": "^1.0.0",
+            "lodash": "^4.17.4"
+          },
+          "dependencies": {
+            "acorn": {
+              "version": "5.7.3",
+              "bundled": true
+            },
+            "acorn-jsx": {
+              "version": "3.0.1",
+              "bundled": true,
+              "requires": {
+                "acorn": "^3.0.4"
+              },
+              "dependencies": {
+                "acorn": {
+                  "version": "3.3.0",
+                  "bundled": true
+                }
+              }
+            },
+            "debug": {
+              "version": "3.2.6",
+              "bundled": true,
+              "requires": {
+                "ms": "^2.1.1"
+              }
+            },
+            "espree": {
+              "version": "3.5.4",
+              "bundled": true,
+              "requires": {
+                "acorn": "^5.5.0",
+                "acorn-jsx": "^3.0.0"
+              }
+            },
+            "ms": {
+              "version": "2.1.1",
+              "bundled": true
+            }
+          }
+        },
         "vue-functional-data-merge": {
           "version": "2.0.7",
           "bundled": true
@@ -12561,32 +13612,18 @@
             "yargs": "^8.0.2"
           },
           "dependencies": {
-            "ajv": {
-              "version": "6.5.4",
-              "bundled": true,
-              "requires": {
-                "fast-deep-equal": "^2.0.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-              }
+            "acorn": {
+              "version": "5.7.3",
+              "bundled": true
             },
             "camelcase": {
               "version": "4.1.0",
               "bundled": true
             },
-            "fast-deep-equal": {
-              "version": "2.0.1",
-              "bundled": true
-            },
             "has-flag": {
               "version": "2.0.0",
               "bundled": true
             },
-            "json-schema-traverse": {
-              "version": "0.4.1",
-              "bundled": true
-            },
             "load-json-file": {
               "version": "2.0.0",
               "bundled": true,
@@ -12732,15 +13769,40 @@
               "bundled": true
             },
             "debug": {
-              "version": "3.2.5",
+              "version": "3.2.6",
               "bundled": true,
               "requires": {
                 "ms": "^2.1.1"
               }
             },
-            "has-flag": {
+            "del": {
               "version": "3.0.0",
-              "bundled": true
+              "bundled": true,
+              "requires": {
+                "globby": "^6.1.0",
+                "is-path-cwd": "^1.0.0",
+                "is-path-in-cwd": "^1.0.0",
+                "p-map": "^1.1.1",
+                "pify": "^3.0.0",
+                "rimraf": "^2.2.8"
+              }
+            },
+            "globby": {
+              "version": "6.1.0",
+              "bundled": true,
+              "requires": {
+                "array-union": "^1.0.1",
+                "glob": "^7.0.3",
+                "object-assign": "^4.0.1",
+                "pify": "^2.0.0",
+                "pinkie-promise": "^2.0.0"
+              },
+              "dependencies": {
+                "pify": {
+                  "version": "2.3.0",
+                  "bundled": true
+                }
+              }
             },
             "is-fullwidth-code-point": {
               "version": "1.0.0",
@@ -12813,7 +13875,7 @@
           },
           "dependencies": {
             "source-list-map": {
-              "version": "2.0.0",
+              "version": "2.0.1",
               "bundled": true
             },
             "source-map": {
@@ -12861,7 +13923,7 @@
           "bundled": true
         },
         "wordwrap": {
-          "version": "0.0.2",
+          "version": "1.0.0",
           "bundled": true
         },
         "wrap-ansi": {
@@ -12894,6 +13956,13 @@
           "version": "1.0.2",
           "bundled": true
         },
+        "write": {
+          "version": "0.2.1",
+          "bundled": true,
+          "requires": {
+            "mkdirp": "^0.5.1"
+          }
+        },
         "xtend": {
           "version": "4.0.1",
           "bundled": true
@@ -12963,20 +14032,12 @@
       }
     },
     "dom-converter": {
-      "version": "0.1.4",
-      "resolved": "http://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz",
-      "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=",
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+      "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
       "dev": true,
       "requires": {
-        "utila": "~0.3"
-      },
-      "dependencies": {
-        "utila": {
-          "version": "0.3.3",
-          "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
-          "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
-          "dev": true
-        }
+        "utila": "~0.4"
       }
     },
     "dom-serializer": {
@@ -12991,7 +14052,7 @@
       "dependencies": {
         "domelementtype": {
           "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+          "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
           "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
           "dev": true
         }
@@ -13004,9 +14065,9 @@
       "dev": true
     },
     "domelementtype": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
-      "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.2.1.tgz",
+      "integrity": "sha512-SQVCLFS2E7G5CRCMdn6K9bIhRj1bS6QBWZfF0TUPh4V/BbqrQ619IdSS3/izn0FZ+9l+uODzaZjb08fjOfablA==",
       "dev": true
     },
     "domhandler": {
@@ -13040,9 +14101,9 @@
       "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
     },
     "duplexify": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
-      "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz",
+      "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==",
       "dev": true,
       "requires": {
         "end-of-stream": "^1.0.0",
@@ -13052,17 +14113,25 @@
       }
     },
     "editorconfig": {
-      "version": "0.15.0",
-      "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.0.tgz",
-      "integrity": "sha512-j7JBoj/bpNzvoTQylfRZSc85MlLNKWQiq5y6gwKhmqD2h1eZ+tH4AXbkhEJD468gjDna/XMx2YtSkCxBRX9OGg==",
+      "version": "0.15.2",
+      "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.2.tgz",
+      "integrity": "sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ==",
       "dev": true,
       "requires": {
-        "@types/commander": "^2.11.0",
-        "@types/semver": "^5.4.0",
-        "commander": "^2.11.0",
-        "lru-cache": "^4.1.1",
-        "semver": "^5.4.1",
+        "@types/node": "^10.11.7",
+        "@types/semver": "^5.5.0",
+        "commander": "^2.19.0",
+        "lru-cache": "^4.1.3",
+        "semver": "^5.6.0",
         "sigmund": "^1.0.1"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.19.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
+          "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
+          "dev": true
+        }
       }
     },
     "ee-first": {
@@ -13078,9 +14147,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.3.72",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.72.tgz",
-      "integrity": "sha512-OFbXEC01Lq7A66e3UywkvWYNN00HO1I9MAPereGe0NIXrt2MeaovL1bbY+951HKG0euUdPBe0L7yfKxgqxBMMw==",
+      "version": "1.3.83",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.83.tgz",
+      "integrity": "sha512-DqJoDarxq50dcHsOOlMLNoy+qQitlMNbYb6wwbE0oUw2veHdRkpNrhmngiUYKMErdJ8SJ48rpJsZTQgy5SoEAA==",
       "dev": true
     },
     "elliptic": {
@@ -13140,9 +14209,9 @@
       }
     },
     "entities": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
-      "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
       "dev": true
     },
     "errno": {
@@ -13248,14 +14317,14 @@
       }
     },
     "express": {
-      "version": "4.16.3",
-      "resolved": "http://registry.npmjs.org/express/-/express-4.16.3.tgz",
-      "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
+      "version": "4.16.4",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+      "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
       "dev": true,
       "requires": {
         "accepts": "~1.3.5",
         "array-flatten": "1.1.1",
-        "body-parser": "1.18.2",
+        "body-parser": "1.18.3",
         "content-disposition": "0.5.2",
         "content-type": "~1.0.4",
         "cookie": "0.3.1",
@@ -13272,10 +14341,10 @@
         "on-finished": "~2.3.0",
         "parseurl": "~1.3.2",
         "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.3",
-        "qs": "6.5.1",
+        "proxy-addr": "~2.0.4",
+        "qs": "6.5.2",
         "range-parser": "~1.2.0",
-        "safe-buffer": "5.1.1",
+        "safe-buffer": "5.1.2",
         "send": "0.16.2",
         "serve-static": "1.13.2",
         "setprototypeof": "1.1.0",
@@ -13283,14 +14352,6 @@
         "type-is": "~1.6.16",
         "utils-merge": "1.0.1",
         "vary": "~1.1.2"
-      },
-      "dependencies": {
-        "safe-buffer": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
-          "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
-          "dev": true
-        }
       }
     },
     "extend-shallow": {
@@ -13355,7 +14416,7 @@
     },
     "fast-deep-equal": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
       "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
       "dev": true
     },
@@ -13366,9 +14427,9 @@
       "dev": true
     },
     "fastparse": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
-      "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+      "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
       "dev": true
     },
     "figures": {
@@ -13465,9 +14526,9 @@
       }
     },
     "follow-redirects": {
-      "version": "1.5.8",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz",
-      "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==",
+      "version": "1.5.9",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz",
+      "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==",
       "dev": true,
       "requires": {
         "debug": "=3.1.0"
@@ -14245,9 +15306,9 @@
       }
     },
     "graceful-fs": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
-      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+      "version": "4.1.15",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
       "dev": true
     },
     "gzip-size": {
@@ -14383,9 +15444,9 @@
       }
     },
     "he": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-      "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
     "hmac-drbg": {
@@ -14416,9 +15477,9 @@
       "dev": true
     },
     "html-comment-regex": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz",
-      "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
+      "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==",
       "dev": true
     },
     "html-entities": {
@@ -14428,15 +15489,15 @@
       "dev": true
     },
     "html-minifier": {
-      "version": "3.5.20",
-      "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.20.tgz",
-      "integrity": "sha512-ZmgNLaTp54+HFKkONyLFEfs5dd/ZOtlquKaTnqIWFmx3Av5zG6ZPcV2d0o9XM2fXOTxxIf6eDcwzFFotke/5zA==",
+      "version": "3.5.21",
+      "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
+      "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
       "dev": true,
       "requires": {
         "camel-case": "3.0.x",
         "clean-css": "4.2.x",
         "commander": "2.17.x",
-        "he": "1.1.x",
+        "he": "1.2.x",
         "param-case": "2.1.x",
         "relateurl": "0.2.x",
         "uglify-js": "3.4.x"
@@ -14472,7 +15533,7 @@
     },
     "htmlparser2": {
       "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
+      "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
       "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=",
       "dev": true,
       "requires": {
@@ -14696,7 +15757,7 @@
     },
     "into-stream": {
       "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
       "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=",
       "requires": {
         "from2": "^2.1.1",
@@ -14979,9 +16040,9 @@
       "dev": true
     },
     "js-beautify": {
-      "version": "1.8.6",
-      "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.8.6.tgz",
-      "integrity": "sha512-TYDZa+lg8vEC5U0OmGQEEwiZ0XFBfvZAUeNOtqflLe+woKuIqF4JzlsBx/C1KVYW5lUewZy2ODL4Obq6sH7a4Q==",
+      "version": "1.8.8",
+      "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.8.8.tgz",
+      "integrity": "sha512-qVNq7ZZ7ZbLdzorvSlRDadS0Rh5oyItaE95v6I4wbbuSiijxn7SnnsV6dvKlcXuO2jX7lK8tn9fBulx34K/Ejg==",
       "dev": true,
       "requires": {
         "config-chain": "~1.1.5",
@@ -15097,7 +16158,7 @@
       "dependencies": {
         "pify": {
           "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
           "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
           "dev": true
         }
@@ -15251,18 +16312,19 @@
       "dev": true
     },
     "md5.js": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
-      "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
       "dev": true,
       "requires": {
         "hash-base": "^3.0.0",
-        "inherits": "^2.0.1"
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
       }
     },
     "media-typer": {
       "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
       "dev": true
     },
@@ -15343,18 +16405,18 @@
       "dev": true
     },
     "mime-db": {
-      "version": "1.36.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
-      "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==",
+      "version": "1.37.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
+      "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==",
       "dev": true
     },
     "mime-types": {
-      "version": "2.1.20",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
-      "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
+      "version": "2.1.21",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
+      "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
       "dev": true,
       "requires": {
-        "mime-db": "~1.36.0"
+        "mime-db": "~1.37.0"
       }
     },
     "mimic-fn": {
@@ -15532,9 +16594,9 @@
       "dev": true
     },
     "neo-async": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz",
-      "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==",
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz",
+      "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==",
       "dev": true
     },
     "nice-try": {
@@ -15648,9 +16710,9 @@
       }
     },
     "nth-check": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
-      "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
       "dev": true,
       "requires": {
         "boolbase": "~1.0.0"
@@ -15870,7 +16932,7 @@
     },
     "os-homedir": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
       "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
       "dev": true
     },
@@ -15885,7 +16947,7 @@
     },
     "os-tmpdir": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
     },
     "osenv": {
@@ -16054,7 +17116,7 @@
     },
     "path-is-absolute": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
       "dev": true
     },
@@ -16126,9 +17188,9 @@
       }
     },
     "popper.js": {
-      "version": "1.14.4",
-      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz",
-      "integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY="
+      "version": "1.14.5",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.5.tgz",
+      "integrity": "sha512-fs4Sd8bZLgEzrk8aS7Em1qh+wcawtE87kRUJQhK6+LndyV1HerX7+LURzAylVaTyWIn5NTB/lyjnWqw/AZ6Yrw=="
     },
     "posix-character-classes": {
       "version": "0.1.1",
@@ -17268,9 +18330,9 @@
       }
     },
     "postcss-modules-extract-imports": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz",
-      "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz",
+      "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==",
       "dev": true,
       "requires": {
         "postcss": "^6.0.1"
@@ -17887,9 +18949,9 @@
       }
     },
     "postcss-value-parser": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
-      "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+      "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
       "dev": true
     },
     "postcss-zindex": {
@@ -18032,16 +19094,17 @@
       "dev": true
     },
     "public-encrypt": {
-      "version": "4.0.2",
-      "resolved": "http://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
-      "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+      "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
       "dev": true,
       "requires": {
         "bn.js": "^4.1.0",
         "browserify-rsa": "^4.0.0",
         "create-hash": "^1.1.0",
         "parse-asn1": "^5.0.0",
-        "randombytes": "^2.0.1"
+        "randombytes": "^2.0.1",
+        "safe-buffer": "^5.1.2"
       }
     },
     "pump": {
@@ -18078,9 +19141,9 @@
       "dev": true
     },
     "qs": {
-      "version": "6.5.1",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
-      "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
       "dev": true
     },
     "query-string": {
@@ -18106,9 +19169,9 @@
       "dev": true
     },
     "randomatic": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz",
-      "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz",
+      "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==",
       "dev": true,
       "requires": {
         "is-number": "^4.0.0",
@@ -18156,46 +19219,25 @@
       "dev": true
     },
     "raw-body": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
-      "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
       "dev": true,
       "requires": {
         "bytes": "3.0.0",
-        "http-errors": "1.6.2",
-        "iconv-lite": "0.4.19",
+        "http-errors": "1.6.3",
+        "iconv-lite": "0.4.23",
         "unpipe": "1.0.0"
       },
       "dependencies": {
-        "depd": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
-          "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
-          "dev": true
-        },
-        "http-errors": {
-          "version": "1.6.2",
-          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
-          "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+        "iconv-lite": {
+          "version": "0.4.23",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+          "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
           "dev": true,
           "requires": {
-            "depd": "1.1.1",
-            "inherits": "2.0.3",
-            "setprototypeof": "1.0.3",
-            "statuses": ">= 1.3.1 < 2"
+            "safer-buffer": ">= 2.1.2 < 3"
           }
-        },
-        "iconv-lite": {
-          "version": "0.4.19",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
-          "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
-          "dev": true
-        },
-        "setprototypeof": {
-          "version": "1.0.3",
-          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
-          "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
-          "dev": true
         }
       }
     },
@@ -18223,7 +19265,7 @@
         },
         "pify": {
           "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
           "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
           "dev": true
         }
@@ -18660,7 +19702,7 @@
     },
     "regjsgen": {
       "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
       "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
       "dev": true
     },
@@ -18694,24 +19736,16 @@
       "dev": true
     },
     "renderkid": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz",
-      "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz",
+      "integrity": "sha512-FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg==",
       "dev": true,
       "requires": {
         "css-select": "^1.1.0",
-        "dom-converter": "~0.1",
+        "dom-converter": "~0.2",
         "htmlparser2": "~3.3.0",
         "strip-ansi": "^3.0.0",
-        "utila": "~0.3"
-      },
-      "dependencies": {
-        "utila": {
-          "version": "0.3.3",
-          "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
-          "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
-          "dev": true
-        }
+        "utila": "^0.4.0"
       }
     },
     "repeat-element": {
@@ -18854,7 +19888,7 @@
     },
     "safe-regex": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
       "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
       "dev": true,
       "requires": {
@@ -18887,9 +19921,9 @@
       "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
     },
     "semver": {
-      "version": "5.5.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
-      "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
       "dev": true
     },
     "send": {
@@ -19153,9 +20187,9 @@
       "integrity": "sha1-gKKyNwq9Vo4c7IwnETHvMKkE+ig="
     },
     "source-list-map": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
-      "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
       "dev": true
     },
     "source-map": {
@@ -19201,9 +20235,9 @@
       "dev": true
     },
     "spdx-correct": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.1.tgz",
-      "integrity": "sha512-hxSPZbRZvSDuOvADntOElzJpenIR7wXJkuoUcUtS0erbgt2fgeaoPIYretfKpslMhfFDY4k0MZ2F5CUzhBsSvQ==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz",
+      "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==",
       "dev": true,
       "requires": {
         "spdx-expression-parse": "^3.0.0",
@@ -19211,9 +20245,9 @@
       }
     },
     "spdx-exceptions": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
-      "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
       "dev": true
     },
     "spdx-expression-parse": {
@@ -19227,9 +20261,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
-      "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz",
+      "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==",
       "dev": true
     },
     "split-string": {
@@ -19384,7 +20418,7 @@
     },
     "style-loader": {
       "version": "0.20.3",
-      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.20.3.tgz",
+      "resolved": "http://registry.npmjs.org/style-loader/-/style-loader-0.20.3.tgz",
       "integrity": "sha512-2I7AVP73MvK33U7B9TKlYZAqdROyMXDYSMvHLX43qy3GCOaJNiV6i0v/sv9idWIaQ42Yn2dNv79Q5mKXbKhAZg==",
       "dev": true,
       "requires": {
@@ -19393,9 +20427,9 @@
       },
       "dependencies": {
         "ajv": {
-          "version": "6.5.4",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
-          "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==",
+          "version": "6.5.5",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz",
+          "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==",
           "dev": true,
           "requires": {
             "fast-deep-equal": "^2.0.1",
@@ -19460,19 +20494,19 @@
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
     },
     "through2": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
-      "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+      "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
       "dev": true,
       "requires": {
-        "readable-stream": "^2.1.5",
+        "readable-stream": "~2.3.6",
         "xtend": "~4.0.1"
       }
     },
     "time-stamp": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.1.0.tgz",
-      "integrity": "sha512-lJbq6KsFhZJtN3fPUVje1tq/hHsJOKUUcUj/MGCiQR6qWBDcyi5kxL9J7/RnaEChCn0+L/DUN2WvemDrkk4i3Q==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.2.0.tgz",
+      "integrity": "sha512-zxke8goJQpBeEgD82CXABeMh0LSJcj7CXEd0OHOg45HgcofF7pxNwZm9+RknpxpDhwN4gFpySkApKfFYfRQnUA==",
       "dev": true
     },
     "timed-out": {
@@ -20178,9 +21212,9 @@
       }
     },
     "webpack-hot-middleware": {
-      "version": "2.24.2",
-      "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.24.2.tgz",
-      "integrity": "sha512-VsBGNMC5JDnab5hbReMjmIYtnvDMT+odLSP49EbLZHwuAoJJDNOi0YLhTe40vvP7u7Be+Ww1mYHjwwelqdnaKA==",
+      "version": "2.24.3",
+      "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.24.3.tgz",
+      "integrity": "sha512-pPlmcdoR2Fn6UhYjAhp1g/IJy1Yc9hD+T6O9mjRcWV2pFbBjIFoJXhP0CoD0xPOhWJuWXuZXGBga9ybbOdzXpg==",
       "dev": true,
       "requires": {
         "ansi-html": "0.0.7",
@@ -20375,7 +21409,7 @@
     },
     "yargs-parser": {
       "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
+      "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
       "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
       "dev": true,
       "requires": {
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
index a50630e..a8deb4b 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
@@ -29,6 +29,9 @@ import ClipboardCopyButton from "../commons/ClipboardCopyButton.vue";
 import NewSSHCredentialModal from "../credentials/NewSSHCredentialModal.vue";
 
 export default {
+  // TODO: disable if the 'value' is not in the list of loaded credentials?
+  // Because it would mean that the user doesn't have access to this credential.
+  // Maybe display 'You don't have access to this credential'.
   name: "ssh-credential-selector",
   props: {},
   mixins: [mixins.VModelMixin],
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue
new file mode 100644
index 0000000..f9bf046
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue
@@ -0,0 +1,32 @@
+<template>
+  <div>
+    <div class="row">
+      <div class="col">
+        <h1 class="h4 mb-4">
+          Gateway Resource Profile - {{ data.gatewayID }}
+        </h1>
+        <b-form-group label="Default SSH Credential" label-for="default-credential-store-token" description="This is the default SSH credential that will be used for storage preferences that don't specify their own SSH credential.">
+          <ssh-credential-selector id="default-credential-store-token" v-model="data.credentialStoreToken">
+            <option :value="null" slot="first">
+              --- Unset the default SSH credential for this gateway
+            </option>
+          </ssh-credential-selector>
+        </b-form-group>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mixins } from "django-airavata-common-ui";
+import SSHCredentialSelector from "../credentials/SSHCredentialSelector.vue";
+
+export default {
+  name: "gateway-resource-profile-editor",
+  mixins: [mixins.VModelMixin],
+  components: {
+    "ssh-credential-selector": SSHCredentialSelector
+  }
+};
+</script>
+
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
new file mode 100644
index 0000000..f6aee83
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
@@ -0,0 +1,87 @@
+<template>
+  <div>
+    <div class="row">
+      <div class="col">
+        <div class="card">
+          <div class="card-body">
+            <gateway-resource-profile-editor v-if="gatewayResourceProfile" v-model="gatewayResourceProfile" />
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col">
+        <div class="card">
+          <div class="card-body">
+            <storage-preference-list v-if="gatewayResourceProfile" :storagePreferences="gatewayResourceProfile.storagePreferences"
+              @updated="updatedStoragePreference" />
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col">
+        <b-button variant="primary" @click="save">
+          Save
+        </b-button>
+        <b-button variant="secondary" @click="cancel">
+          Cancel
+        </b-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { services } from "django-airavata-api";
+import GatewayResourceProfileEditor from "./GatewayResourceProfileEditor.vue";
+import StoragePreferenceEditor from "./StoragePreferenceEditor.vue";
+import StoragePreferenceList from "./StoragePreferenceList.vue";
+
+export default {
+  name: "gateway-resource-profile-editor-container",
+  components: {
+    GatewayResourceProfileEditor,
+    StoragePreferenceEditor,
+    StoragePreferenceList
+  },
+  data() {
+    return {
+      gatewayResourceProfile: null,
+      gatewayResourceProfileClone: null
+    };
+  },
+  created() {
+    services.GatewayResourceProfileService.current().then(gwp => {
+      this.gatewayResourceProfile = gwp;
+      this.gatewayResourceProfileClone = gwp.clone();
+    });
+  },
+  methods: {
+    save() {
+      services.GatewayResourceProfileService.update({
+        lookup: this.gatewayResourceProfile.gatewayID,
+        data: this.gatewayResourceProfile
+      }).then(gwp => {
+        this.gatewayResourceProfile = gwp;
+        this.gatewayResourceProfileClone = gwp.clone();
+      });
+    },
+    cancel() {
+      this.gatewayResourceProfile = this.gatewayResourceProfileClone.clone();
+    },
+    updatedStoragePreference(updatedStoragePreference) {
+      const index = this.gatewayResourceProfile.storagePreferences.findIndex(
+        sp =>
+          sp.storageResourceId === updatedStoragePreference.storageResourceId
+      );
+      this.gatewayResourceProfile.storagePreferences.splice(
+        index,
+        1,
+        updatedStoragePreference
+      );
+    }
+  }
+};
+</script>
+
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
new file mode 100644
index 0000000..5487fd5
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
@@ -0,0 +1,42 @@
+<template>
+  <div>
+    <b-form-group label="Login username" label-for="login-username">
+      <b-form-input id="login-username" v-model="data.loginUserName" type="text" />
+    </b-form-group>
+    <b-form-group label="File System Root Location" label-for="filesystem-root-location">
+      <b-form-input id="filesystem-root-location" v-model="data.fileSystemRootLocation" type="text" />
+    </b-form-group>
+    <b-form-group label="Resource Specific SSH Credential" label-for="default-credential-store-token" description="This is the SSH credential that will be used for to move data to/from this storage resource.">
+      <ssh-credential-selector id="default-credential-store-token" v-model="data.resourceSpecificCredentialStoreToken">
+        <option v-if="gatewayResourceProfile && gatewayResourceProfile.credentialStoreToken" :value="null" slot="first">
+          --- Use the default SSH credential for {{ gatewayResourceProfile.gatewayID }}
+        </option>
+      </ssh-credential-selector>
+    </b-form-group>
+  </div>
+</template>
+
+<script>
+import { mixins } from "django-airavata-common-ui";
+import { services } from "django-airavata-api";
+import SSHCredentialSelector from "../credentials/SSHCredentialSelector.vue";
+
+export default {
+  name: "storage-preference-editor",
+  mixins: [mixins.VModelMixin],
+  components: {
+    "ssh-credential-selector": SSHCredentialSelector,
+  },
+  data() {
+    return {
+      gatewayResourceProfile: null
+    };
+  },
+  created() {
+    services.GatewayResourceProfileService.current().then(gwp => {
+      this.gatewayResourceProfile = gwp;
+    });
+  }
+};
+</script>
+
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
new file mode 100644
index 0000000..5a8a4d5
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
@@ -0,0 +1,106 @@
+<template>
+  <list-layout @add-new-item="newStoragePreference" :items="decoratedStoragePreferences" title="Storage Preferences"
+    new-item-button-text="New Storage Preference">
+    <template slot="item-list" slot-scope="slotProps">
+
+      <b-table striped hover :fields="fields" :items="slotProps.items" sort-by="storageResourceId">
+        <template slot="action" slot-scope="data">
+          <b-link @click="toggleDetails(data)">
+            Edit
+            <i class="fa fa-edit" aria-hidden="true"></i>
+          </b-link>
+        </template>
+        <template slot="row-details" slot-scope="row">
+          <b-card>
+            <storage-preference-editor :value="row.item" @input="updatedStoragePreference" />
+            <b-button size="sm" @click="toggleDetails(row)">Close</b-button>
+          </b-card>
+        </template>
+      </b-table>
+    </template>
+  </list-layout>
+</template>
+
+<script>
+import { models } from "django-airavata-api";
+import { layouts } from "django-airavata-common-ui";
+import StoragePreferenceEditor from "./StoragePreferenceEditor.vue";
+
+export default {
+  name: "storage-preference-list",
+  components: {
+    "list-layout": layouts.ListLayout,
+    StoragePreferenceEditor
+  },
+  props: {
+    storagePreferences: {
+      type: Array,
+      required: true
+    }
+  },
+  data() {
+    return {
+      showingDetails: {},
+    }
+  },
+  computed: {
+    fields() {
+      return [
+        {
+          label: "Name",
+          key: "storageResourceId",
+          sortable: true,
+          formatter: value => this.getStorageResourceName(value)
+        },
+        {
+          label: "Username",
+          key: "loginUserName"
+        },
+        {
+          label: "SSH Credential",
+          key: "resourceSpecificCredentialStoreToken",
+          formatter: value => this.getCredentialName(value)
+        },
+        {
+          label: "File System Location",
+          key: "fileSystemRootLocation",
+          formatter: value => this.formatFileSystemLocation(value)
+        },
+        {
+          label: "Action",
+          key: "action"
+        }
+      ];
+    },
+    decoratedStoragePreferences() {
+      return this.storagePreferences.map(sp => {
+        const spClone = sp.clone();
+        spClone._showDetails = this.showingDetails[spClone.storageResourceId];
+        return spClone;
+      });
+    }
+  },
+  methods: {
+    getStorageResourceName(storageResourceId) {
+      // TODO: fetch storage resources
+      return storageResourceId;
+    },
+    getCredentialName(token) {
+      // TODO: fetch credential name
+      return token;
+    },
+    formatFileSystemLocation(fileSystemRootLocation) {
+      // TODO: truncate to fit
+      return fileSystemRootLocation;
+    },
+    updatedStoragePreference(newValue) {
+      this.$emit('updated', newValue);
+    },
+    toggleDetails(row) {
+      row.toggleDetails();
+      this.showingDetails[row.item.storageResourceId] = !this.showingDetails[row.item.storageResourceId];
+    }
+  }
+};
+</script>
+
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceListItem.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceListItem.vue
new file mode 100644
index 0000000..13818a9
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceListItem.vue
@@ -0,0 +1,10 @@
+<template>
+
+</template>
+
+<script>
+export default {
+  name: "storage-preference-list-item"
+};
+</script>
+
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/router.js b/django_airavata/apps/admin/static/django_airavata_admin/src/router.js
index 71eef6f..14d2c20 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/router.js
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/router.js
@@ -8,6 +8,7 @@ import ComputePreference from "./components/admin/group_resource_preferences/Com
 import ComputeResourcePreferenceDashboard from "./components/dashboards/ComputeResourcePreferenceDashboard";
 import CredentialStoreDashboard from "./components/dashboards/CredentialStoreDashboard";
 import ExperimentsDashboard from "./components/dashboards/ExperimentDashboard.vue";
+import GatewayResourceProfileEditorContainer from "./components/gatewayprofile/GatewayResourceProfileEditorContainer.vue";
 import GroupComputeResourcePreference from "./components/admin/group_resource_preferences/GroupComputeResourcePreference";
 import VueRouter from "vue-router";
 
@@ -116,6 +117,11 @@ const routes = [
     path: "/credentials",
     component: CredentialStoreDashboard,
     name: "credential_store"
+  },
+  {
+    path: "/gateway-resource-profile",
+    component: GatewayResourceProfileEditorContainer,
+    name: "gateway-resource-profile"
   }
 ];
 export default new VueRouter({
diff --git a/django_airavata/apps/admin/templates/admin/admin_base.html b/django_airavata/apps/admin/templates/admin/admin_base.html
index 97e5c66..613b84c 100644
--- a/django_airavata/apps/admin/templates/admin/admin_base.html
+++ b/django_airavata/apps/admin/templates/admin/admin_base.html
@@ -18,6 +18,9 @@
         <a href="{% url 'django_airavata_admin:group_resource_profile' %}" class="c-nav__item {% if request.active_nav_item == 'group_resource_profile' %}is-active{% endif %}" data-toggle=tooltip data-placement=right title="Group Resource Profile">
             <i class="fa fa-server"></i> <span class=sr-only>Group Resource Profile</span>
         </a>
+        <a href="{% url 'django_airavata_admin:gateway_resource_profile' %}" class="c-nav__item {% if request.active_nav_item == 'gateway_resource_profile' %}is-active{% endif %}" data-toggle=tooltip data-placement=right title="Gateway Resource Profile">
+            <i class="fa fa-tasks"></i> <span class=sr-only>Gateway Resource Profile</span>
+        </a>
 {% endblock %}
 {% block scripts %}
     {{ block.super }}
diff --git a/django_airavata/apps/admin/urls.py b/django_airavata/apps/admin/urls.py
index 92e06e6..47ab077 100644
--- a/django_airavata/apps/admin/urls.py
+++ b/django_airavata/apps/admin/urls.py
@@ -9,4 +9,6 @@ urlpatterns = [
     url(r'^credentials/', views.credential_store, name='credential_store'),
     url(r'^group-resource-profiles/', views.group_resource_profile,
         name='group_resource_profile'),
+    url(r'^gateway-resource-profile/', views.gateway_resource_profile,
+        name='gateway_resource_profile'),
 ]
diff --git a/django_airavata/apps/admin/views.py b/django_airavata/apps/admin/views.py
index 8f1df4b..68582d4 100644
--- a/django_airavata/apps/admin/views.py
+++ b/django_airavata/apps/admin/views.py
@@ -29,3 +29,9 @@ def compute_resource(request):
 def group_resource_profile(request):
     request.active_nav_item = 'group_resource_profile'
     return render(request, 'admin/admin_base.html')
+
+
+@login_required
+def gateway_resource_profile(request):
+    request.active_nav_item = 'gateway_resource_profile'
+    return render(request, 'admin/admin_base.html')
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 82499fc..e9bb617 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -22,6 +22,10 @@ from airavata.model.appcatalog.computeresource.ttypes import (
     BatchQueue,
     ComputeResourceDescription
 )
+from airavata.model.appcatalog.gatewayprofile.ttypes import (
+    GatewayResourceProfile,
+    StoragePreference
+)
 from airavata.model.appcatalog.groupresourceprofile.ttypes import (
     GroupResourceProfile
 )
@@ -64,9 +68,9 @@ class FullyEncodedHyperlinkedIdentityField(
                 "[{}] of object [{}]".format(
                     lookup_value, self.lookup_field, obj))
             raise
-        # Bit of a hack. Django's URL reversing does URL encoding but it doesn't
-        # encode all characters including some like '/' that are used in URL
-        # mappings.
+        # Bit of a hack. Django's URL reversing does URL encoding but it
+        # doesn't encode all characters including some like '/' that are used
+        # in URL mappings.
         kwargs = {self.lookup_url_kwarg: "__PLACEHOLDER__"}
         url = self.reverse(view_name, kwargs=kwargs,
                            request=request, format=format)
@@ -152,7 +156,7 @@ class GroupSerializer(thrift_utils.create_serializer_class(GroupModel)):
 
     class Meta:
         required = ('name',)
-        read_only = ('id', 'ownerId')
+        read_only = ('ownerId',)
 
     def create(self, validated_data):
         group = super().create(validated_data)
@@ -576,8 +580,9 @@ class SharedEntitySerializer(serializers.Serializer):
 
     def update(self, instance, validated_data):
         # Compute lists of ids to grant/revoke READ/WRITE
-        existing_user_permissions = {user['user'].airavataInternalUserId: user['permissionType']
-                                     for user in instance['userPermissions']}
+        existing_user_permissions = {
+            user['user'].airavataInternalUserId: user['permissionType']
+            for user in instance['userPermissions']}
         new_user_permissions = {
             user['user']['airavataInternalUserId']:
             user['permissionType']
@@ -679,3 +684,23 @@ class CredentialSummarySerializer(
         return request.airavata_client.userHasAccess(
             request.authz_token, credential_summary.token,
             ResourcePermissionType.WRITE)
+
+
+class StoragePreferenceSerializer(
+        thrift_utils.create_serializer_class(StoragePreference)):
+
+    def to_representation(self, instance):
+        ret = super().to_representation(instance)
+        # Convert empty string to null
+        if ret['resourceSpecificCredentialStoreToken'] == '':
+            ret['resourceSpecificCredentialStoreToken'] = None
+        return ret
+
+
+class GatewayResourceProfileSerializer(
+        thrift_utils.create_serializer_class(GatewayResourceProfile)):
+    url = FullyEncodedHyperlinkedIdentityField(
+        view_name='django_airavata_api:gateway-resource-profile-detail',
+        lookup_field='gatewayID',
+        lookup_url_kwarg='gateway_id')
+    storagePreferences = StoragePreferenceSerializer(many=True)
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/index.js b/django_airavata/apps/api/static/django_airavata_api/js/index.js
index 9cfa626..1ec0d71 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/index.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/index.js
@@ -26,6 +26,7 @@ import Project from "./models/Project";
 import ResourcePermissionType from "./models/ResourcePermissionType";
 import SetEnvPaths from "./models/SetEnvPaths";
 import SharedEntity from "./models/SharedEntity";
+import StoragePreference from "./models/StoragePreference";
 import SummaryType from "./models/SummaryType";
 import UserPermission from "./models/UserPermission";
 
@@ -79,6 +80,7 @@ exports.models = {
   ResourcePermissionType,
   SetEnvPaths,
   SharedEntity,
+  StoragePreference,
   SummaryType,
   UserPermission
 };
@@ -95,6 +97,7 @@ exports.services = {
   ExperimentSearchService,
   ExperimentService,
   FullExperimentService,
+  GatewayResourceProfileService: ServiceFactory.service("GatewayResourceProfiles"),
   GlobusJobSubmissionService,
   GridFTPDataMovementService,
   GroupResourceProfileService: ServiceFactory.service("GroupResourceProfiles"),
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/GatewayResourceProfile.js b/django_airavata/apps/api/static/django_airavata_api/js/models/GatewayResourceProfile.js
new file mode 100644
index 0000000..5826e68
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/GatewayResourceProfile.js
@@ -0,0 +1,21 @@
+import BaseModel from "./BaseModel";
+import StoragePreference from "./StoragePreference";
+
+const FIELDS = [
+  "gatewayID",
+  "credentialStoreToken",
+  "computeResourcePreferences",
+  {
+    name: "storagePreferences",
+    type: StoragePreference,
+    list: true
+  },
+  "identityServerTenant",
+  "identityServerPwdCredToken"
+];
+
+export default class GatewayResourceProfile extends BaseModel {
+  constructor(data = {}) {
+    super(FIELDS, data);
+  }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/StoragePreference.js b/django_airavata/apps/api/static/django_airavata_api/js/models/StoragePreference.js
new file mode 100644
index 0000000..82087b7
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/StoragePreference.js
@@ -0,0 +1,14 @@
+import BaseModel from "./BaseModel";
+
+const FIELDS = [
+  "storageResourceId",
+  "loginUserName",
+  "fileSystemRootLocation",
+  "resourceSpecificCredentialStoreToken"
+];
+
+export default class StoragePreference extends BaseModel {
+  constructor(data = {}) {
+    super(FIELDS, data);
+  }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
index d1f52f9..7f22e29 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
@@ -2,6 +2,7 @@ import ApplicationDeploymentDescription from "./models/ApplicationDeploymentDesc
 import ApplicationModule from "./models/ApplicationModule";
 import ComputeResourceDescription from "./models/ComputeResourceDescription";
 import CredentialSummary from "./models/CredentialSummary";
+import GatewayResourceProfile from "./models/GatewayResourceProfile";
 import Group from "./models/Group";
 import GroupResourceProfile from "./models/GroupResourceProfile";
 import SharedEntity from "./models/SharedEntity";
@@ -178,6 +179,33 @@ export default {
     ],
     modelClass: CredentialSummary
   },
+  GatewayResourceProfiles: {
+    url: "/api/gateway-resource-profiles/",
+    viewSet: [
+      {
+        name: "list"
+      },
+      {
+        name: "create"
+      },
+      {
+        name: "retrieve"
+      },
+      {
+        name: "update"
+      },
+      {
+        name: "delete"
+      },
+      {
+        name: "current",
+        url: "/api/gateway-resource-profile/",
+        requestType: "get",
+        modelClass: GatewayResourceProfile
+      }
+    ],
+    modelClass: GatewayResourceProfile
+  },
   GroupResourceProfiles: {
     url: "/api/group-resource-profiles/",
     viewSet: true,
diff --git a/django_airavata/apps/api/thrift_utils.py b/django_airavata/apps/api/thrift_utils.py
index 258ee4b..943e7d6 100644
--- a/django_airavata/apps/api/thrift_utils.py
+++ b/django_airavata/apps/api/thrift_utils.py
@@ -3,6 +3,7 @@ Used to create Django Rest Framework serializers for Apache Thrift Data Types
 """
 import copy
 import datetime
+import logging
 
 from django.utils import six
 from rest_framework.serializers import (
@@ -14,12 +15,15 @@ from rest_framework.serializers import (
     Field,
     IntegerField,
     ListField,
+    ListSerializer,
     Serializer,
     SerializerMetaclass,
     ValidationError
 )
 from thrift.Thrift import TType
 
+logger = logging.getLogger(__name__)
+
 # used to map apache thrift data types to django serializer fields
 mapping = {
     TType.STRING: CharField,
@@ -122,8 +126,10 @@ def create_serializer_class(thrift_data_type, enable_date_time_conversion=False)
             fields = self.fields
             params = copy.deepcopy(validated_data)
             for field_name, serializer in fields.items():
-                if isinstance(serializer, ListField):
-                    if (params[field_name] is not None or not serializer.allow_null):
+                if (isinstance(serializer, ListField) or
+                        isinstance(serializer, ListSerializer)):
+                    if (params[field_name] is not None or
+                            not serializer.allow_null):
                         if isinstance(serializer.child, Serializer):
                             params[field_name] = [serializer.child.create(
                                 item) for item in params[field_name]]
diff --git a/django_airavata/apps/api/urls.py b/django_airavata/apps/api/urls.py
index 1227c62..b610aba 100644
--- a/django_airavata/apps/api/urls.py
+++ b/django_airavata/apps/api/urls.py
@@ -32,6 +32,9 @@ router.register(r'compute-resources', views.ComputeResourceViewSet,
                 base_name='compute-resource')
 router.register(r'credential-summaries', views.CredentialSummaryViewSet,
                 base_name='credential-summary')
+router.register(r'gateway-resource-profiles',
+                views.GatewayResourceProfileViewSet,
+                base_name='gateway-resource-profile')
 
 app_name = 'django_airavata_api'
 urlpatterns = [
@@ -56,6 +59,9 @@ urlpatterns = [
         name="unicore_ftp_data_movement"),
     url(r'^data/movement/scp', views.ScpDataMovementView.as_view(),
         name="scp_ftp_data_movement"),
+    url(r'^gateway-resource-profile',
+        views.GetCurrentGatewayResourceProfile.as_view(),
+        name="current_gateway_resource_profile"),
 ]
 
 if logger.isEnabledFor(logging.DEBUG):
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 88fd2f2..625667f 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -914,3 +914,44 @@ class CredentialSummaryViewSet(APIBackedViewSet):
         elif instance.type == SummaryType.PASSWD:
             self.request.airavata_client.deletePWDCredential(
                 self.authz_token, instance.token)
+
+
+class GatewayResourceProfileViewSet(APIBackedViewSet):
+    serializer_class = serializers.GatewayResourceProfileSerializer
+    lookup_field = 'gateway_id'
+    lookup_value_regex = '[^/]+'
+
+    def get_list(self):
+        return self.request.airavata_client.getAllGatewayResourceProfiles(
+            self.authz_token)
+
+    def get_instance(self, lookup_value):
+        return self.request.airavata_client.getGatewayResourceProfile(
+            self.authz_token, lookup_value)
+
+    def perform_create(self, serializer):
+        gateway_resource_profile = serializer.save()
+        self.request.airavata_client.registerGatewayResourceProfile(
+            self.authz_token, gateway_resource_profile)
+
+    def perform_update(self, serializer):
+        gateway_resource_profile = serializer.save()
+        self.request.airavata_client.updateGatewayResourceProfile(
+            self.authz_token,
+            gateway_resource_profile.gatewayID,
+            gateway_resource_profile)
+
+    def perform_destroy(self, instance):
+        self.request.airavata_client.deleteGatewayResourceProfile(
+            self.authz_token, instance.gatewayID)
+
+
+class GetCurrentGatewayResourceProfile(APIView):
+
+    def get(self, request, format=None):
+        gateway_resource_profile = \
+            request.airavata_client.getGatewayResourceProfile(
+                request.authz_token, settings.GATEWAY_ID)
+        serializer = serializers.GatewayResourceProfileSerializer(
+            gateway_resource_profile, context={'request': request})
+        return Response(serializer.data)


[airavata-django-portal] 06/06: AIRAVATA-2907 Delete storage prefs

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit d30077beb635aaa5d004f8bd7f2c6702f35b9837
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Fri Nov 16 16:11:18 2018 -0500

    AIRAVATA-2907 Delete storage prefs
---
 .../GatewayResourceProfileEditorContainer.vue            | 12 +++++++++++-
 .../components/gatewayprofile/StoragePreferenceList.vue  | 16 ++++++++++++++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
index 6f175ed..3e827c0 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
@@ -15,7 +15,7 @@
           <div class="card-body">
             <storage-preference-list v-if="gatewayResourceProfile" :storagePreferences="gatewayResourceProfile.storagePreferences"
               :default-credential-store-token="gatewayResourceProfile.credentialStoreToken" @updated="updatedStoragePreference"
-              @added="addedStoragePreference" />
+              @added="addedStoragePreference" @delete="deleteStoragePreference" />
           </div>
         </div>
       </div>
@@ -88,6 +88,16 @@ export default {
       }).then(sp => {
         this.gatewayResourceProfile.storagePreferences.push(sp);
       });
+    },
+    deleteStoragePreference(storageResourceId) {
+      services.StoragePreferenceService.delete({
+        lookup: storageResourceId
+      }).then(() => {
+        const index = this.gatewayResourceProfile.storagePreferences.findIndex(
+          sp => sp.storageResourceId === storageResourceId
+        );
+        this.gatewayResourceProfile.storagePreferences.splice(index, 1);
+      });
     }
   }
 };
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
index 00c259f..7ec5c1c 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
@@ -23,10 +23,13 @@
 
       <b-table striped hover :fields="fields" :items="slotProps.items" sort-by="storageResourceId">
         <template slot="action" slot-scope="data">
-          <b-link @click="toggleDetails(data)">
+          <b-link class="action-link" @click="toggleDetails(data)">
             Edit
             <i class="fa fa-edit" aria-hidden="true"></i>
           </b-link>
+          <delete-link @delete="deleteStoragePreference(data.item.storageResourceId)">
+            Are you sure you want to delete the storage preference for {{ getStorageResourceName(data.item.storageResourceId) }}?
+          </delete-link>
         </template>
         <template slot="row-details" slot-scope="row">
           <b-card>
@@ -42,12 +45,13 @@
 
 <script>
 import { models, services, utils } from "django-airavata-api";
-import { layouts } from "django-airavata-common-ui";
+import { components, layouts } from "django-airavata-common-ui";
 import StoragePreferenceEditor from "./StoragePreferenceEditor.vue";
 
 export default {
   name: "storage-preference-list",
   components: {
+    "delete-link": components.DeleteLink,
     "list-layout": layouts.ListLayout,
     StoragePreferenceEditor
   },
@@ -172,6 +176,9 @@ export default {
         row.item.storageResourceId
       ];
     },
+    deleteStoragePreference(storageResourceId) {
+      this.$emit('delete', storageResourceId);
+    },
     addNewStoragePreference() {
       this.newStoragePreference = new models.StoragePreference();
       this.showNewItemEditor = true;
@@ -187,3 +194,8 @@ export default {
 };
 </script>
 
+<style scoped>
+.action-link {
+  white-space: nowrap;
+}
+</style>


[airavata-django-portal] 04/06: AIRAVATA-2907 Better default ssh key description; filter storage options

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit dd63cc19d120771a172f5ae8a88ea41cb10c9aec
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Fri Nov 16 15:30:56 2018 -0500

    AIRAVATA-2907 Better default ssh key description; filter storage options
---
 .../ComputePreference.vue                          | 19 ++++++---
 .../GroupComputeResourcePreference.vue             |  3 --
 .../credentials/SSHCredentialSelector.vue          | 48 ++++++++++++++++++----
 .../GatewayResourceProfileEditor.vue               |  6 +--
 .../GatewayResourceProfileEditorContainer.vue      |  3 +-
 .../gatewayprofile/StoragePreferenceEditor.vue     | 31 +++++++-------
 .../gatewayprofile/StoragePreferenceList.vue       | 16 ++++++--
 7 files changed, 84 insertions(+), 42 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
index c3105eb..459b404 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
@@ -18,11 +18,18 @@
               </b-form-input>
             </b-form-group>
             <b-form-group label="SSH Credential" label-for="credential-store-token">
-              <ssh-credential-selector v-model="data.resourceSpecificCredentialStoreToken">
-                <option v-if="localGroupResourceProfile && localGroupResourceProfile.defaultCredentialStoreToken"
-                  :value="null" slot="first">
-                  --- Use the default SSH credential for {{ localGroupResourceProfile.groupResourceProfileName }}
-                </option>
+              <ssh-credential-selector v-model="data.resourceSpecificCredentialStoreToken"
+                :null-option-default-credential-token="localGroupResourceProfile.defaultCredentialStoreToken"
+                :null-option-disabled="!localGroupResourceProfile.defaultCredentialStoreToken">
+                <template slot="null-option-label" slot-scope="nullOptionLabelScope">
+                  <span v-if="nullOptionLabelScope.defaultCredentialSummary">
+                    Use the default SSH credential for {{ localGroupResourceProfile.groupResourceProfileName }} ({{
+                    nullOptionLabelScope.defaultCredentialSummary.description }})
+                  </span>
+                  <span v-else>
+                    Select a SSH credential
+                  </span>
+                </template>
               </ssh-credential-selector>
             </b-form-group>
             <b-form-group label="Allocation Project Number" label-for="allocation-number">
@@ -73,7 +80,7 @@ import BatchQueueResourcePolicy from "./BatchQueueResourcePolicy.vue";
 import SSHCredentialSelector from "../../credentials/SSHCredentialSelector.vue";
 
 import { models, services } from "django-airavata-api";
-import { mixins } from "django-airavata-common-ui"
+import { mixins } from "django-airavata-common-ui";
 
 export default {
   name: "compute-preference",
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue
index 206ca98..db35c83 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue
@@ -15,9 +15,6 @@
             </b-form-group>
             <b-form-group label="Default SSH Credential" label-for="default-credential-store-token">
               <ssh-credential-selector id="default-credential-store-token" v-model="data.defaultCredentialStoreToken">
-                <option :value="null" slot="first">
-                  --- Unset the default SSH credential for this profile
-                </option>
               </ssh-credential-selector>
             </b-form-group>
             <share-button ref="shareButton" :entity-id="id" />
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
index a8deb4b..622f984 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
@@ -2,16 +2,19 @@
   <div>
     <b-input-group>
       <b-form-select v-model="data" :options="credentialStoreTokenOptions">
-        <template v-if="$slots.first" slot="first">
-          <slot name="first">
-            <option :value="null">
-              Use the default SSH credential
-            </option>
+        <option v-if="nullOption" slot="first" :value="null" :disabled="nullOptionDisabled">
+          <slot name="null-option-label" :defaultCredentialSummary="defaultCredentialSummary">
+            <span v-if="defaultCredentialSummary">
+              Use the default SSH credential ({{ defaultCredentialSummary.description }})
+            </span>
+            <span v-else>
+              Unset the default SSH credential
+            </span>
           </slot>
-        </template>
+        </option>
       </b-form-select>
       <b-input-group-append>
-        <clipboard-copy-button variant="secondary" :disabled="!selectedCredential" :text="selectedCredential ? selectedCredential.publicKey : null">
+        <clipboard-copy-button variant="secondary" :disabled="!copySSHPublicKeyText" :text="copySSHPublicKeyText">
         </clipboard-copy-button>
         <b-button variant="secondary" @click="showNewSSHCredentialModal">
           <font-awesome-icon icon="plus" />
@@ -24,7 +27,7 @@
 
 <script>
 import { services } from "django-airavata-api";
-import { mixins } from "django-airavata-common-ui"
+import { mixins } from "django-airavata-common-ui";
 import ClipboardCopyButton from "../commons/ClipboardCopyButton.vue";
 import NewSSHCredentialModal from "../credentials/NewSSHCredentialModal.vue";
 
@@ -33,7 +36,20 @@ export default {
   // Because it would mean that the user doesn't have access to this credential.
   // Maybe display 'You don't have access to this credential'.
   name: "ssh-credential-selector",
-  props: {},
+  props: {
+    nullOption: {
+      type: Boolean,
+      default: true
+    },
+    // This is the default credential token that will be used if the null option is selected
+    nullOptionDefaultCredentialToken: {
+      type: String
+    },
+    nullOptionDisabled: {
+      type: Boolean,
+      default: false
+    }
+  },
   mixins: [mixins.VModelMixin],
   components: {
     ClipboardCopyButton,
@@ -63,6 +79,20 @@ export default {
       return this.credentials
         ? this.credentials.find(cred => cred.token === this.data)
         : null;
+    },
+    defaultCredentialSummary() {
+      return this.nullOptionDefaultCredentialToken && this.credentials
+        ? this.credentials.find(
+            cred => cred.token === this.nullOptionDefaultCredentialToken
+          )
+        : null;
+    },
+    copySSHPublicKeyText() {
+      return this.selectedCredential
+        ? this.selectedCredential.publicKey
+        : this.defaultCredentialSummary
+          ? this.defaultCredentialSummary.publicKey
+          : null;
     }
   },
   methods: {
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue
index f9bf046..244bdb6 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditor.vue
@@ -6,11 +6,7 @@
           Gateway Resource Profile - {{ data.gatewayID }}
         </h1>
         <b-form-group label="Default SSH Credential" label-for="default-credential-store-token" description="This is the default SSH credential that will be used for storage preferences that don't specify their own SSH credential.">
-          <ssh-credential-selector id="default-credential-store-token" v-model="data.credentialStoreToken">
-            <option :value="null" slot="first">
-              --- Unset the default SSH credential for this gateway
-            </option>
-          </ssh-credential-selector>
+          <ssh-credential-selector id="default-credential-store-token" v-model="data.credentialStoreToken"/>
         </b-form-group>
       </div>
     </div>
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
index 303ab56..6f175ed 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
@@ -14,7 +14,8 @@
         <div class="card">
           <div class="card-body">
             <storage-preference-list v-if="gatewayResourceProfile" :storagePreferences="gatewayResourceProfile.storagePreferences"
-              @updated="updatedStoragePreference" @added="addedStoragePreference" />
+              :default-credential-store-token="gatewayResourceProfile.credentialStoreToken" @updated="updatedStoragePreference"
+              @added="addedStoragePreference" />
           </div>
         </div>
       </div>
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
index 5487fd5..53edfad 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
@@ -7,10 +7,16 @@
       <b-form-input id="filesystem-root-location" v-model="data.fileSystemRootLocation" type="text" />
     </b-form-group>
     <b-form-group label="Resource Specific SSH Credential" label-for="default-credential-store-token" description="This is the SSH credential that will be used for to move data to/from this storage resource.">
-      <ssh-credential-selector id="default-credential-store-token" v-model="data.resourceSpecificCredentialStoreToken">
-        <option v-if="gatewayResourceProfile && gatewayResourceProfile.credentialStoreToken" :value="null" slot="first">
-          --- Use the default SSH credential for {{ gatewayResourceProfile.gatewayID }}
-        </option>
+      <ssh-credential-selector id="default-credential-store-token" v-model="data.resourceSpecificCredentialStoreToken"
+        :null-option-default-credential-token="defaultCredentialStoreToken" :null-option-disabled="!defaultCredentialStoreToken">
+        <template slot="null-option-label" slot-scope="nullOptionLabelScope">
+          <span v-if="nullOptionLabelScope.defaultCredentialSummary">
+            Use the gateway's default SSH credential ({{ nullOptionLabelScope.defaultCredentialSummary.description }})
+          </span>
+          <span v-else>
+            Select a SSH credential
+          </span>
+        </template>
       </ssh-credential-selector>
     </b-form-group>
   </div>
@@ -18,25 +24,20 @@
 
 <script>
 import { mixins } from "django-airavata-common-ui";
-import { services } from "django-airavata-api";
 import SSHCredentialSelector from "../credentials/SSHCredentialSelector.vue";
 
 export default {
   name: "storage-preference-editor",
   mixins: [mixins.VModelMixin],
   components: {
-    "ssh-credential-selector": SSHCredentialSelector,
+    "ssh-credential-selector": SSHCredentialSelector
   },
-  data() {
-    return {
-      gatewayResourceProfile: null
-    };
+  props: {
+    defaultCredentialStoreToken: {
+      type: String,
+      required: true
+    }
   },
-  created() {
-    services.GatewayResourceProfileService.current().then(gwp => {
-      this.gatewayResourceProfile = gwp;
-    });
-  }
 };
 </script>
 
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
index fd66c04..7f1424d 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
@@ -6,7 +6,7 @@
         <b-form-group label="Storage Resource" label-for="storage-resource">
           <b-form-select id="storage-resource" v-model="newStoragePreference.storageResourceId" :options="storageResourceOptions" />
         </b-form-group>
-        <storage-preference-editor v-model="newStoragePreference" />
+        <storage-preference-editor v-model="newStoragePreference" :default-credential-store-token="defaultCredentialStoreToken" />
         <div class="row">
           <div class="col">
             <b-button variant="primary" @click="saveNewStoragePreference">
@@ -30,7 +30,8 @@
         </template>
         <template slot="row-details" slot-scope="row">
           <b-card>
-            <storage-preference-editor :value="row.item" @input="updatedStoragePreference" />
+            <storage-preference-editor :value="row.item" @input="updatedStoragePreference"
+              :default-credential-store-token="defaultCredentialStoreToken" />
             <b-button size="sm" @click="toggleDetails(row)">Close</b-button>
           </b-card>
         </template>
@@ -54,6 +55,9 @@ export default {
     storagePreferences: {
       type: Array,
       required: true
+    },
+    defaultCredentialStoreToken: {
+      type: String
     }
   },
   data() {
@@ -100,10 +104,16 @@ export default {
         return spClone;
       });
     },
+    currentStoragePreferenceIds() {
+      return this.storagePreferences.map(sp => sp.storageResourceId);
+    },
     storageResourceOptions() {
       const options = [];
       for (const key in this.storageResourceNames) {
-        if (this.storageResourceNames.hasOwnProperty(key)) {
+        if (
+          this.storageResourceNames.hasOwnProperty(key) &&
+          this.currentStoragePreferenceIds.indexOf(key) < 0
+        ) {
           const name = this.storageResourceNames[key];
           options.push({
             value: key,


[airavata-django-portal] 05/06: AIRAVATA-2907 Formatting storage pref listing

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit fd358e4781ff804e1c3e4a2602d1ea3b6a7b75c3
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Fri Nov 16 15:49:56 2018 -0500

    AIRAVATA-2907 Formatting storage pref listing
---
 .../gatewayprofile/StoragePreferenceList.vue       | 43 ++++++++++++++++------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
index 7f1424d..00c259f 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
@@ -65,7 +65,8 @@ export default {
       showingDetails: {},
       showNewItemEditor: false,
       newStoragePreference: null,
-      storageResourceNames: null
+      storageResourceNames: null,
+      credentials: null
     };
   },
   computed: {
@@ -88,8 +89,7 @@ export default {
         },
         {
           label: "File System Location",
-          key: "fileSystemRootLocation",
-          formatter: value => this.formatFileSystemLocation(value)
+          key: "fileSystemRootLocation"
         },
         {
           label: "Action",
@@ -122,25 +122,46 @@ export default {
         }
       }
       return utils.StringUtils.sortIgnoreCase(options, a => a.text);
+    },
+    defaultCredentialSummary() {
+      if (this.defaultCredentialStoreToken && this.credentials) {
+        return this.credentials.find(
+          cred => cred.token === this.defaultCredentialStoreToken
+        );
+      } else {
+        return null;
+      }
     }
   },
   created() {
     services.StorageResourceService.names().then(names => {
       this.storageResourceNames = names;
     });
+    services.CredentialSummaryService.allSSHCredentials().then(
+      creds => (this.credentials = creds)
+    );
   },
   methods: {
     getStorageResourceName(storageResourceId) {
-      // TODO: fetch storage resources
-      return storageResourceId;
+      if (
+        this.storageResourceNames &&
+        storageResourceId in this.storageResourceNames
+      ) {
+        return this.storageResourceNames[storageResourceId];
+      } else {
+        return storageResourceId.substring(0, 10) + "...";
+      }
     },
     getCredentialName(token) {
-      // TODO: fetch credential name
-      return token;
-    },
-    formatFileSystemLocation(fileSystemRootLocation) {
-      // TODO: truncate to fit
-      return fileSystemRootLocation;
+      if (token === null && this.defaultCredentialSummary) {
+        return this.defaultCredentialSummary.description + " (default)";
+      } else if (this.credentials) {
+        const cred = this.credentials.find(cred => cred.token === token);
+        if (cred) {
+          return cred.description;
+        }
+      }
+      return "...";
     },
     updatedStoragePreference(newValue) {
       this.$emit("updated", newValue);


[airavata-django-portal] 02/06: AIRAVATA-2907 Add new storage preference UI

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 523600110cf81f7cf1033c0380e5886439de3dca
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Thu Nov 15 12:11:36 2018 -0500

    AIRAVATA-2907 Add new storage preference UI
---
 .../GatewayResourceProfileEditorContainer.vue      |  9 +++-
 .../gatewayprofile/StoragePreferenceList.vue       | 62 ++++++++++++++++++++--
 .../gatewayprofile/StoragePreferenceListItem.vue   | 10 ----
 django_airavata/apps/api/serializers.py            | 17 ++++++
 .../api/static/django_airavata_api/js/index.js     |  2 +
 .../js/models/StorageResourceDescription.js        | 17 ++++++
 .../django_airavata_api/js/service_config.js       | 21 ++++++++
 django_airavata/apps/api/urls.py                   |  5 ++
 django_airavata/apps/api/views.py                  | 52 ++++++++++++++++++
 .../static/common/js/layouts/ListLayout.vue        |  5 ++
 10 files changed, 184 insertions(+), 16 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
index f6aee83..303ab56 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/GatewayResourceProfileEditorContainer.vue
@@ -14,7 +14,7 @@
         <div class="card">
           <div class="card-body">
             <storage-preference-list v-if="gatewayResourceProfile" :storagePreferences="gatewayResourceProfile.storagePreferences"
-              @updated="updatedStoragePreference" />
+              @updated="updatedStoragePreference" @added="addedStoragePreference" />
           </div>
         </div>
       </div>
@@ -80,6 +80,13 @@ export default {
         1,
         updatedStoragePreference
       );
+    },
+    addedStoragePreference(newStoragePreference) {
+      services.StoragePreferenceService.create({
+        data: newStoragePreference
+      }).then(sp => {
+        this.gatewayResourceProfile.storagePreferences.push(sp);
+      });
     }
   }
 };
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
index 5a8a4d5..fd66c04 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceList.vue
@@ -1,6 +1,24 @@
 <template>
-  <list-layout @add-new-item="newStoragePreference" :items="decoratedStoragePreferences" title="Storage Preferences"
+  <list-layout @add-new-item="addNewStoragePreference" :items="decoratedStoragePreferences" title="Storage Preferences"
     new-item-button-text="New Storage Preference">
+    <template slot="new-item-editor">
+      <b-card v-if="showNewItemEditor" title="New Storage Preference">
+        <b-form-group label="Storage Resource" label-for="storage-resource">
+          <b-form-select id="storage-resource" v-model="newStoragePreference.storageResourceId" :options="storageResourceOptions" />
+        </b-form-group>
+        <storage-preference-editor v-model="newStoragePreference" />
+        <div class="row">
+          <div class="col">
+            <b-button variant="primary" @click="saveNewStoragePreference">
+              Save
+            </b-button>
+            <b-button variant="secondary" @click="cancelNewStoragePreference">
+              Cancel
+            </b-button>
+          </div>
+        </div>
+      </b-card>
+    </template>
     <template slot="item-list" slot-scope="slotProps">
 
       <b-table striped hover :fields="fields" :items="slotProps.items" sort-by="storageResourceId">
@@ -22,7 +40,7 @@
 </template>
 
 <script>
-import { models } from "django-airavata-api";
+import { models, services, utils } from "django-airavata-api";
 import { layouts } from "django-airavata-common-ui";
 import StoragePreferenceEditor from "./StoragePreferenceEditor.vue";
 
@@ -41,7 +59,10 @@ export default {
   data() {
     return {
       showingDetails: {},
-    }
+      showNewItemEditor: false,
+      newStoragePreference: null,
+      storageResourceNames: null
+    };
   },
   computed: {
     fields() {
@@ -78,8 +99,26 @@ export default {
         spClone._showDetails = this.showingDetails[spClone.storageResourceId];
         return spClone;
       });
+    },
+    storageResourceOptions() {
+      const options = [];
+      for (const key in this.storageResourceNames) {
+        if (this.storageResourceNames.hasOwnProperty(key)) {
+          const name = this.storageResourceNames[key];
+          options.push({
+            value: key,
+            text: name
+          });
+        }
+      }
+      return utils.StringUtils.sortIgnoreCase(options, a => a.text);
     }
   },
+  created() {
+    services.StorageResourceService.names().then(names => {
+      this.storageResourceNames = names;
+    });
+  },
   methods: {
     getStorageResourceName(storageResourceId) {
       // TODO: fetch storage resources
@@ -94,11 +133,24 @@ export default {
       return fileSystemRootLocation;
     },
     updatedStoragePreference(newValue) {
-      this.$emit('updated', newValue);
+      this.$emit("updated", newValue);
     },
     toggleDetails(row) {
       row.toggleDetails();
-      this.showingDetails[row.item.storageResourceId] = !this.showingDetails[row.item.storageResourceId];
+      this.showingDetails[row.item.storageResourceId] = !this.showingDetails[
+        row.item.storageResourceId
+      ];
+    },
+    addNewStoragePreference() {
+      this.newStoragePreference = new models.StoragePreference();
+      this.showNewItemEditor = true;
+    },
+    saveNewStoragePreference() {
+      this.$emit("added", this.newStoragePreference);
+      this.showNewItemEditor = false;
+    },
+    cancelNewStoragePreference() {
+      this.showNewItemEditor = false;
     }
   }
 };
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceListItem.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceListItem.vue
deleted file mode 100644
index 13818a9..0000000
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceListItem.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-<template>
-
-</template>
-
-<script>
-export default {
-  name: "storage-preference-list-item"
-};
-</script>
-
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index e9bb617..d1bf697 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -29,6 +29,9 @@ from airavata.model.appcatalog.gatewayprofile.ttypes import (
 from airavata.model.appcatalog.groupresourceprofile.ttypes import (
     GroupResourceProfile
 )
+from airavata.model.appcatalog.storageresource.ttypes import (
+    StorageResourceDescription
+)
 from airavata.model.application.io.ttypes import InputDataObjectType
 from airavata.model.credential.store.ttypes import (
     CredentialSummary,
@@ -688,6 +691,10 @@ class CredentialSummarySerializer(
 
 class StoragePreferenceSerializer(
         thrift_utils.create_serializer_class(StoragePreference)):
+    url = FullyEncodedHyperlinkedIdentityField(
+        view_name='django_airavata_api:storage-preference-detail',
+        lookup_field='storageResourceId',
+        lookup_url_kwarg='storage_resource_id')
 
     def to_representation(self, instance):
         ret = super().to_representation(instance)
@@ -704,3 +711,13 @@ class GatewayResourceProfileSerializer(
         lookup_field='gatewayID',
         lookup_url_kwarg='gateway_id')
     storagePreferences = StoragePreferenceSerializer(many=True)
+
+
+class StorageResourceSerializer(
+        thrift_utils.create_serializer_class(StorageResourceDescription)):
+    url = FullyEncodedHyperlinkedIdentityField(
+        view_name='django_airavata_api:storage-resource-detail',
+        lookup_field='storageResourceId',
+        lookup_url_kwarg='storage_resource_id')
+    creationTime = UTCPosixTimestampDateTimeField()
+    updateTime = UTCPosixTimestampDateTimeField()
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/index.js b/django_airavata/apps/api/static/django_airavata_api/js/index.js
index 1ec0d71..9184f0e 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/index.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/index.js
@@ -108,6 +108,8 @@ exports.services = {
   ServiceFactory,
   SharedEntityService: ServiceFactory.service("SharedEntities"),
   SshJobSubmissionService,
+  StoragePreferenceService: ServiceFactory.service("StoragePreferences"),
+  StorageResourceService: ServiceFactory.service("StorageResources"),
   UnicoreDataMovementService,
   UnicoreJobSubmissionService,
   UserProfileService
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/StorageResourceDescription.js b/django_airavata/apps/api/static/django_airavata_api/js/models/StorageResourceDescription.js
new file mode 100644
index 0000000..554c543
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/StorageResourceDescription.js
@@ -0,0 +1,17 @@
+import BaseModel from "./BaseModel";
+
+const FIELDS = [
+  "storageResourceId",
+  "hostName",
+  "storageResourceDescription",
+  "enabled",
+  "dataMovementInterfaces",
+  "creationTime",
+  "updateTime"
+];
+
+export default class StorageResourceDescription extends BaseModel {
+  constructor(data = {}) {
+    super(FIELDS, data);
+  }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
index 7f22e29..138c870 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
@@ -6,6 +6,8 @@ import GatewayResourceProfile from "./models/GatewayResourceProfile";
 import Group from "./models/Group";
 import GroupResourceProfile from "./models/GroupResourceProfile";
 import SharedEntity from "./models/SharedEntity";
+import StoragePreference from "./models/StoragePreference";
+import StorageResourceDescription from "./models/StorageResourceDescription";
 import UserProfile from "./models/UserProfile";
 import ApplicationInterfaceDefinition from "./models/ApplicationInterfaceDefinition";
 import BatchQueue from "./models/BatchQueue";
@@ -239,6 +241,25 @@ export default {
     ],
     modelClass: SharedEntity
   },
+  StoragePreferences: {
+    url: "/api/storage-preferences/",
+    viewSet: true,
+    modelClass: StoragePreference
+  },
+  StorageResources: {
+    url: "/api/storage-resources",
+    viewSet: [
+      {
+        name: "retrieve"
+      },
+      {
+        name: "names",
+        url: "/api/storage-resources/all_names/",
+        requestType: "get"
+      }
+    ],
+    modelClass: StorageResourceDescription
+  },
   UserProfiles: {
     url: "/api/user-profiles",
     viewSet: [
diff --git a/django_airavata/apps/api/urls.py b/django_airavata/apps/api/urls.py
index b610aba..a8d6a8b 100644
--- a/django_airavata/apps/api/urls.py
+++ b/django_airavata/apps/api/urls.py
@@ -30,11 +30,16 @@ router.register(r'shared-entities', views.SharedEntityViewSet,
                 base_name='shared-entity')
 router.register(r'compute-resources', views.ComputeResourceViewSet,
                 base_name='compute-resource')
+router.register(r'storage-resources', views.StorageResourceViewSet,
+                base_name='storage-resource')
 router.register(r'credential-summaries', views.CredentialSummaryViewSet,
                 base_name='credential-summary')
 router.register(r'gateway-resource-profiles',
                 views.GatewayResourceProfileViewSet,
                 base_name='gateway-resource-profile')
+router.register(r'storage-preferences',
+                views.StoragePreferenceViewSet,
+                base_name='storage-preference')
 
 app_name = 'django_airavata_api'
 urlpatterns = [
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 625667f..16c2ed0 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -955,3 +955,55 @@ class GetCurrentGatewayResourceProfile(APIView):
         serializer = serializers.GatewayResourceProfileSerializer(
             gateway_resource_profile, context={'request': request})
         return Response(serializer.data)
+
+
+class StorageResourceViewSet(mixins.RetrieveModelMixin,
+                             GenericAPIBackedViewSet):
+    serializer_class = serializers.StorageResourceSerializer
+    lookup_field = 'storage_resource_id'
+    lookup_value_regex = '[^/]+'
+
+    def get_instance(self, lookup_value, format=None):
+        return self.request.airavata_client.getStorageResource(
+            self.authz_token, lookup_value)
+
+    @list_route()
+    def all_names(self, request, format=None):
+        """Return a map of compute resource names keyed by resource id."""
+        return Response(
+            request.airavata_client.getAllStorageResourceNames(
+                request.authz_token))
+
+
+class StoragePreferenceViewSet(APIBackedViewSet):
+    serializer_class = serializers.StoragePreferenceSerializer
+    lookup_field = 'storage_resource_id'
+    lookup_value_regex = '[^/]+'
+
+    def get_list(self):
+        return self.request.airavata_client.getAllGatewayStoragePreferences(
+            self.authz_token, settings.GATEWAY_ID)
+
+    def get_instance(self, lookup_value):
+        return self.request.airavata_client.getGatewayStoragePreference(
+            self.authz_token, settings.GATEWAY_ID, lookup_value)
+
+    def perform_create(self, serializer):
+        storage_preference = serializer.save()
+        self.request.airavata_client.addGatewayStoragePreference(
+            self.authz_token,
+            settings.GATEWAY_ID,
+            storage_preference.storageResourceId,
+            storage_preference)
+
+    def perform_update(self, serializer):
+        storage_preference = serializer.save()
+        self.request.airavata_client.updateGatewayStoragePreference(
+            self.authz_token,
+            settings.GATEWAY_ID,
+            storage_preference.storageResourceId,
+            storage_preference)
+
+    def perform_destroy(self, instance):
+        self.request.airavata_client.deleteGatewayStoragePreference(
+            self.authz_token, settings.GATEWAY_ID, instance.storageResourceId)
diff --git a/django_airavata/static/common/js/layouts/ListLayout.vue b/django_airavata/static/common/js/layouts/ListLayout.vue
index 3a28b7d..ec27700 100644
--- a/django_airavata/static/common/js/layouts/ListLayout.vue
+++ b/django_airavata/static/common/js/layouts/ListLayout.vue
@@ -22,6 +22,11 @@
     </div>
     <div class="row">
       <div class="col">
+        <slot name="new-item-editor"></slot>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col">
         <slot name="item-list" :items="itemsList">Item List goes here</slot>
         <pager v-if="itemsPaginator" :paginator="itemsPaginator" next="nextItems" v-on:previous="previousItems"></pager>
       </div>


[airavata-django-portal] 03/06: AIRAVATA-2907 Only allow Admins to edit GatewayResourceProfile

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit da40a7ba995556c05fd657bcd65e3fb9de461134
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Thu Nov 15 13:05:14 2018 -0500

    AIRAVATA-2907 Only allow Admins to edit GatewayResourceProfile
---
 django_airavata/apps/admin/templates/admin/admin_base.html | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/django_airavata/apps/admin/templates/admin/admin_base.html b/django_airavata/apps/admin/templates/admin/admin_base.html
index 613b84c..6cf7e9d 100644
--- a/django_airavata/apps/admin/templates/admin/admin_base.html
+++ b/django_airavata/apps/admin/templates/admin/admin_base.html
@@ -18,9 +18,11 @@
         <a href="{% url 'django_airavata_admin:group_resource_profile' %}" class="c-nav__item {% if request.active_nav_item == 'group_resource_profile' %}is-active{% endif %}" data-toggle=tooltip data-placement=right title="Group Resource Profile">
             <i class="fa fa-server"></i> <span class=sr-only>Group Resource Profile</span>
         </a>
+        {% if request.is_gateway_admin %}
         <a href="{% url 'django_airavata_admin:gateway_resource_profile' %}" class="c-nav__item {% if request.active_nav_item == 'gateway_resource_profile' %}is-active{% endif %}" data-toggle=tooltip data-placement=right title="Gateway Resource Profile">
             <i class="fa fa-tasks"></i> <span class=sr-only>Gateway Resource Profile</span>
         </a>
+        {% endif %}
 {% endblock %}
 {% block scripts %}
     {{ block.super }}