]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add feature toggle for NFS 32419/head
authorErnesto Puerta <epuertat@redhat.com>
Wed, 4 Mar 2020 20:31:50 +0000 (21:31 +0100)
committerErnesto Puerta <epuertat@redhat.com>
Wed, 11 Mar 2020 14:03:58 +0000 (15:03 +0100)
- New NFS feature toggle added.
- Fixed regression which broke FeatureToggles in the main menu.
- Added extensive unit testing to NavigationComponent
- Added ng-mocks to improve test isolation and performance (~7x, 139s to
20s)
- Added ng-bullet package to improve unit testing performance (2x, 20s
to 9s)
- Added Rxjs Schedulers to implement NgZone.runOutsideAngular in a Rxjs
friendly way (based on
    https://stackoverflow.com/questions/43121400/run-ngrx-effect-outside-of-angulars-zone-to-prevent-timeout-in-protractor)

Minor issues found from exhaustive unit testing:
- Missing permissions in Cluster menu:
  - `permissions.log.read` and `permissions.prometheus.read`
- Missing classes:
  - Block -> Images: `tc_submenuitem_block_images`
  - Block -> iSCSI: `tc_submenuitem_block_iscsi`
- Typos:
  - class `tc_submenuitem_hosts` assigned to OSD menu (instead of
      `tc_submenuitem_osd`)
  - `tc_menuitem_cephs` -> `tc_menuitem_cephfs`

Minor changes:
- Previously, Cluster Map -> CRUSH Map required both OSD and Host
permissions. Now it only requires OSD permissions (there are no
references to hosts in CRUSH Map page). Nevertheless, all system roles
setting OSD permission also set Host's, so no impact expected.
- Previously, Cluster -> Monitoring menu was hidden when both Prometheus
or Alertmanager weren't configured. Now it's displayed and when clicked
on it shows the helper banner indicating that further configuration is
required. This change removes the dependency on the PrometheusService.

Fixes: https://tracker.ceph.com/issues/43419
Fixes: https://tracker.ceph.com/issues/43715
Signed-off-by: Ernesto Puerta <epuertat@redhat.com>
12 files changed:
doc/mgr/dashboard_plugins/feature_toggles.inc.rst
src/pybind/mgr/dashboard/controllers/nfsganesha.py
src/pybind/mgr/dashboard/frontend/package-lock.json
src/pybind/mgr/dashboard/frontend/package.json
src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts
src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html
src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/services/ngzone-scheduler.service.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/plugins/feature_toggles.py
src/pybind/mgr/dashboard/services/ganesha.py

index b02448664a9bf9d73ebeecced9a6e13ba9ae2dcf..5153e7092c80f1450cb8f75e8da6bca1d4c990a5 100644 (file)
@@ -21,6 +21,7 @@ The list of features that can be enabled/disabled is:
    - iSCSI: ``iscsi``
 - **Filesystem (Cephfs)**: ``cephfs``
 - **Objects (RGW)**: ``rgw`` (including daemon, user and bucket management).
+- **NFS**: ``nfs-ganesha`` exports.
 
 By default all features come enabled.
 
@@ -32,6 +33,7 @@ To retrieve a list of features and their current statuses::
   Feature 'mirroring': 'enabled'
   Feature 'rbd': 'enabled'
   Feature 'rgw': 'enabled'
+  Feature 'nfs': 'enabled'
 
 To enable or disable the status of a single or multiple features::
 
index 157b94d46d4bfb8200f71ec110d272fd41fe812e..18a2a3bf029c60b09f397a1fa80aaa94db211228 100644 (file)
@@ -102,7 +102,7 @@ class NFSGanesha(RESTController):
         try:
             Ganesha.get_ganesha_clusters()
         except NFSException as e:
-            status['message'] = str(e)
+            status['message'] = str(e)  # type: ignore
             status['available'] = False
 
         return status
index 2764ddec4bbaff7f59914da0944b6b5c66370fc8..5b2e79752108284dd983252e377991d196f11129 100644 (file)
             "anymatch": "^2.0.0",
             "async-each": "^1.0.1",
             "braces": "^2.3.2",
-            "fsevents": "2.1.2",
+            "fsevents": "^1.2.7",
             "glob-parent": "^3.1.0",
             "inherits": "^2.0.3",
             "is-binary-path": "^1.0.0",
           },
           "dependencies": {
             "fsevents": {
-              "version": "2.1.2"
+              "version": "1.2.11",
+              "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+              "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "bindings": "^1.5.0",
+                "nan": "^2.12.1",
+                "node-pre-gyp": "*"
+              },
+              "dependencies": {
+                "abbrev": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ansi-regex": {
+                  "version": "2.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "aproba": {
+                  "version": "1.2.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "are-we-there-yet": {
+                  "version": "1.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "delegates": "^1.0.0",
+                    "readable-stream": "^2.0.6"
+                  }
+                },
+                "balanced-match": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "brace-expansion": {
+                  "version": "1.1.11",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "balanced-match": "^1.0.0",
+                    "concat-map": "0.0.1"
+                  }
+                },
+                "chownr": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "code-point-at": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "concat-map": {
+                  "version": "0.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "console-control-strings": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "core-util-is": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "debug": {
+                  "version": "3.2.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ms": "^2.1.1"
+                  }
+                },
+                "deep-extend": {
+                  "version": "0.6.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "delegates": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "detect-libc": {
+                  "version": "1.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "fs-minipass": {
+                  "version": "1.2.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.6.0"
+                  }
+                },
+                "fs.realpath": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "gauge": {
+                  "version": "2.7.4",
+                  "bundled": true,
+                  "dev": 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.6",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "iconv-lite": {
+                  "version": "0.4.24",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safer-buffer": ">= 2.1.2 < 3"
+                  }
+                },
+                "ignore-walk": {
+                  "version": "3.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimatch": "^3.0.4"
+                  }
+                },
+                "inflight": {
+                  "version": "1.0.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "once": "^1.3.0",
+                    "wrappy": "1"
+                  }
+                },
+                "inherits": {
+                  "version": "2.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ini": {
+                  "version": "1.3.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "is-fullwidth-code-point": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "number-is-nan": "^1.0.0"
+                  }
+                },
+                "isarray": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minimatch": {
+                  "version": "3.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "brace-expansion": "^1.1.7"
+                  }
+                },
+                "minimist": {
+                  "version": "0.0.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minipass": {
+                  "version": "2.9.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.0"
+                  }
+                },
+                "minizlib": {
+                  "version": "1.3.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.9.0"
+                  }
+                },
+                "mkdirp": {
+                  "version": "0.5.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimist": "0.0.8"
+                  }
+                },
+                "ms": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "needle": {
+                  "version": "2.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "debug": "^3.2.6",
+                    "iconv-lite": "^0.4.4",
+                    "sax": "^1.2.4"
+                  }
+                },
+                "node-pre-gyp": {
+                  "version": "0.14.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "detect-libc": "^1.0.2",
+                    "mkdirp": "^0.5.1",
+                    "needle": "^2.2.1",
+                    "nopt": "^4.0.1",
+                    "npm-packlist": "^1.1.6",
+                    "npmlog": "^4.0.2",
+                    "rc": "^1.2.7",
+                    "rimraf": "^2.6.1",
+                    "semver": "^5.3.0",
+                    "tar": "^4.4.2"
+                  }
+                },
+                "nopt": {
+                  "version": "4.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "abbrev": "1",
+                    "osenv": "^0.1.4"
+                  }
+                },
+                "npm-bundled": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "npm-normalize-package-bin": "^1.0.1"
+                  }
+                },
+                "npm-normalize-package-bin": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "npm-packlist": {
+                  "version": "1.4.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ignore-walk": "^3.0.1",
+                    "npm-bundled": "^1.0.1"
+                  }
+                },
+                "npmlog": {
+                  "version": "4.1.2",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "object-assign": {
+                  "version": "4.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "once": {
+                  "version": "1.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "wrappy": "1"
+                  }
+                },
+                "os-homedir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "os-tmpdir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "osenv": {
+                  "version": "0.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "os-homedir": "^1.0.0",
+                    "os-tmpdir": "^1.0.0"
+                  }
+                },
+                "path-is-absolute": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "process-nextick-args": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "rc": {
+                  "version": "1.2.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "deep-extend": "^0.6.0",
+                    "ini": "~1.3.0",
+                    "minimist": "^1.2.0",
+                    "strip-json-comments": "~2.0.1"
+                  },
+                  "dependencies": {
+                    "minimist": {
+                      "version": "1.2.0",
+                      "bundled": true,
+                      "dev": true,
+                      "optional": true
+                    }
+                  }
+                },
+                "readable-stream": {
+                  "version": "2.3.6",
+                  "bundled": true,
+                  "dev": 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.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "glob": "^7.1.3"
+                  }
+                },
+                "safe-buffer": {
+                  "version": "5.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "safer-buffer": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "sax": {
+                  "version": "1.2.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "semver": {
+                  "version": "5.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "set-blocking": {
+                  "version": "2.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "signal-exit": {
+                  "version": "3.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "string-width": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": 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,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "~5.1.0"
+                  }
+                },
+                "strip-ansi": {
+                  "version": "3.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ansi-regex": "^2.0.0"
+                  }
+                },
+                "strip-json-comments": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "tar": {
+                  "version": "4.4.13",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "chownr": "^1.1.1",
+                    "fs-minipass": "^1.2.5",
+                    "minipass": "^2.8.6",
+                    "minizlib": "^1.2.1",
+                    "mkdirp": "^0.5.0",
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.3"
+                  }
+                },
+                "util-deprecate": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "wide-align": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "string-width": "^1.0.2 || 2"
+                  }
+                },
+                "wrappy": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "yallist": {
+                  "version": "3.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                }
+              }
             }
           }
         },
           }
         },
         "fsevents": {
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "bindings": "^1.5.0",
-            "nan": "^2.12.1",
-            "node-pre-gyp": "*"
-          },
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+          "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
           "dependencies": {
             "abbrev": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "aproba": {
               "version": "1.2.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "are-we-there-yet": {
               "version": "1.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "delegates": "^1.0.0",
             "balanced-match": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "brace-expansion": {
               "version": "1.1.11",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "balanced-match": "^1.0.0",
             "chownr": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "concat-map": {
               "version": "0.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "core-util-is": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "debug": {
               "version": "3.2.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ms": "^2.1.1"
             "deep-extend": {
               "version": "0.6.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "delegates": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "detect-libc": {
               "version": "1.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "fs-minipass": {
               "version": "1.2.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.6.0"
             "fs.realpath": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "gauge": {
               "version": "2.7.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "aproba": "^1.0.3",
             "glob": {
               "version": "7.1.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "fs.realpath": "^1.0.0",
             "has-unicode": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "iconv-lite": {
               "version": "0.4.24",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safer-buffer": ">= 2.1.2 < 3"
             "ignore-walk": {
               "version": "3.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimatch": "^3.0.4"
             "inflight": {
               "version": "1.0.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "once": "^1.3.0",
             "inherits": {
               "version": "2.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ini": {
               "version": "1.3.5",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "is-fullwidth-code-point": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
             "isarray": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minimatch": {
               "version": "3.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "brace-expansion": "^1.1.7"
             "minimist": {
               "version": "0.0.8",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minipass": {
               "version": "2.9.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
             "minizlib": {
               "version": "1.3.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.9.0"
             "mkdirp": {
               "version": "0.5.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimist": "0.0.8"
             "ms": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "needle": {
               "version": "2.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "debug": "^3.2.6",
             "node-pre-gyp": {
               "version": "0.14.0",
               "bundled": true,
-              "dev": true,
-              "optional": true,
               "requires": {
                 "detect-libc": "^1.0.2",
                 "mkdirp": "^0.5.1",
             "nopt": {
               "version": "4.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "abbrev": "1",
             "npm-bundled": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "npm-normalize-package-bin": "^1.0.1"
             "npm-normalize-package-bin": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "npm-packlist": {
               "version": "1.4.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ignore-walk": "^3.0.1",
             "npmlog": {
               "version": "4.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "are-we-there-yet": "~1.1.2",
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "object-assign": {
               "version": "4.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "once": {
               "version": "1.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "wrappy": "1"
             "os-homedir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "os-tmpdir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "osenv": {
               "version": "0.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "os-homedir": "^1.0.0",
             "path-is-absolute": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "process-nextick-args": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "rc": {
               "version": "1.2.8",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "deep-extend": "^0.6.0",
                 "minimist": {
                   "version": "1.2.0",
                   "bundled": true,
-                  "dev": true,
                   "optional": true
                 }
               }
             "readable-stream": {
               "version": "2.3.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "core-util-is": "~1.0.0",
             "rimraf": {
               "version": "2.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "glob": "^7.1.3"
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "safer-buffer": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "sax": {
               "version": "1.2.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "semver": {
               "version": "5.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "set-blocking": {
               "version": "2.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "signal-exit": {
               "version": "3.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "string-width": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
             "string_decoder": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "~5.1.0"
             "strip-ansi": {
               "version": "3.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
             "strip-json-comments": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "tar": {
               "version": "4.4.13",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "chownr": "^1.1.1",
             "util-deprecate": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "wide-align": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "string-width": "^1.0.2 || 2"
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "yallist": {
               "version": "3.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             }
-          },
-          "version": "2.1.2"
+          }
         },
         "get-caller-file": {
           "version": "2.0.5",
           }
         },
         "mem": {
-          "dev": true,
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+          "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
           "requires": {
             "map-age-cleaner": "^0.1.1",
             "mimic-fn": "^2.0.0",
             "p-is-promise": "^2.0.0"
-          },
-          "version": "4.3.0"
+          }
         },
         "mimic-fn": {
           "version": "2.1.0",
           "requires": {
             "execa": "^1.0.0",
             "lcid": "^2.0.0",
-            "mem": "4.3.0"
+            "mem": "^4.0.0"
           },
           "dependencies": {
             "mem": {
-              "version": "4.3.0"
-            }
-          }
+              "version": "4.3.0",
+              "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+              "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+              "dev": true,
+              "requires": {
+                "map-age-cleaner": "^0.1.1",
+                "mimic-fn": "^2.0.0",
+                "p-is-promise": "^2.0.0"
+              }
+            }
+          }
         },
         "p-limit": {
           "version": "2.2.2",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "json5": "^2.1.0",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.13",
         "resolve": "^1.3.2",
         "semver": "^5.4.1",
         "source-map": "^0.5.0"
           }
         },
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         },
         "semver": {
           "version": "5.7.1",
       "requires": {
         "@babel/types": "^7.8.3",
         "jsesc": "^2.5.1",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.13",
         "source-map": "^0.5.0"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         },
         "source-map": {
           "version": "0.5.7",
       "requires": {
         "@babel/helper-function-name": "^7.8.3",
         "@babel/types": "^7.8.3",
-        "lodash": "4.17.15"
+        "lodash": "^4.17.13"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
         "@babel/helper-split-export-declaration": "^7.8.3",
         "@babel/template": "^7.8.3",
         "@babel/types": "^7.8.3",
-        "lodash": "4.17.15"
+        "lodash": "^4.17.13"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
       "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==",
       "dev": true,
       "requires": {
-        "lodash": "4.17.15"
+        "lodash": "^4.17.13"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.8.3",
-        "lodash": "4.17.15"
+        "lodash": "^4.17.13"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
         "@babel/types": "^7.8.3",
         "debug": "^4.1.0",
         "globals": "^11.1.0",
-        "lodash": "4.17.15"
+        "lodash": "^4.17.13"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
       "dev": true,
       "requires": {
         "esutils": "^2.0.2",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.13",
         "to-fast-properties": "^2.0.0"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
         "inside": "^1.0.0",
         "json5": "^2.1.0",
         "live-server": "^1.2.1",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.15",
         "loglevel": "^1.6.4",
         "loglevel-plugin-prefix": "^0.8.4",
         "lunr": "^2.3.6",
           }
         },
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
     "@types/simplebar": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/@types/simplebar/-/simplebar-2.4.2.tgz",
-      "integrity": "sha512-omSnWgcQ5hGANK8MijABHDNtj7bM2GH80g8wVqeRmaePJ2lPN4RmbrVihEbYtnovW2aS51a0joITsb6+Q1HnnA=="
+      "integrity": "sha512-omSnWgcQ5hGANK8MijABHDNtj7bM2GH80g8wVqeRmaePJ2lPN4RmbrVihEbYtnovW2aS51a0joITsb6+Q1HnnA==",
+      "dev": true
     },
     "@types/source-list-map": {
       "version": "0.1.2",
       "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
       "dev": true,
       "requires": {
-        "lodash": "4.17.15"
+        "lodash": "^4.17.14"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
         "dom-serializer": "~0.1.1",
         "entities": "~1.1.1",
         "htmlparser2": "^3.9.1",
-        "lodash": "4.17.15",
+        "lodash": "^4.15.0",
         "parse5": "^3.0.1"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         },
         "parse5": {
           "version": "3.0.3",
       "requires": {
         "anymatch": "~3.1.1",
         "braces": "~3.0.2",
-        "fsevents": "2.1.2",
+        "fsevents": "~2.1.2",
         "glob-parent": "~5.1.0",
         "is-binary-path": "~2.1.0",
         "is-glob": "~4.0.1",
       },
       "dependencies": {
         "fsevents": {
-          "version": "2.1.2"
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+          "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
+          "dev": true,
+          "optional": true
         },
         "glob-parent": {
           "version": "5.1.0",
         "readable-stream": "1 || 2"
       }
     },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
-    },
-    "fsevents": {
-      "dev": true,
-      "optional": true,
-      "version": "2.1.2"
-    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+    },
+    "fsevents": {
+      "version": "1.2.11",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+      "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "bindings": "^1.5.0",
+        "nan": "^2.12.1",
+        "node-pre-gyp": "*"
+      },
+      "dependencies": {
+        "abbrev": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "ansi-regex": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "aproba": {
+          "version": "1.2.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "are-we-there-yet": {
+          "version": "1.1.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "delegates": "^1.0.0",
+            "readable-stream": "^2.0.6"
+          }
+        },
+        "balanced-match": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "brace-expansion": {
+          "version": "1.1.11",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "chownr": {
+          "version": "1.1.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "code-point-at": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "console-control-strings": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "core-util-is": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "debug": {
+          "version": "3.2.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "deep-extend": {
+          "version": "0.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "delegates": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "detect-libc": {
+          "version": "1.0.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "fs-minipass": {
+          "version": "1.2.7",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.6.0"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "gauge": {
+          "version": "2.7.4",
+          "bundled": true,
+          "dev": 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.6",
+          "bundled": true,
+          "dev": 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,
+          "dev": true,
+          "optional": true
+        },
+        "iconv-lite": {
+          "version": "0.4.24",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        },
+        "ignore-walk": {
+          "version": "3.0.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minimatch": "^3.0.4"
+          }
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "once": "^1.3.0",
+            "wrappy": "1"
+          }
+        },
+        "inherits": {
+          "version": "2.0.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "ini": {
+          "version": "1.3.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "minimist": {
+          "version": "0.0.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "minipass": {
+          "version": "2.9.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.0"
+          }
+        },
+        "minizlib": {
+          "version": "1.3.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.9.0"
+          }
+        },
+        "mkdirp": {
+          "version": "0.5.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "needle": {
+          "version": "2.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "debug": "^3.2.6",
+            "iconv-lite": "^0.4.4",
+            "sax": "^1.2.4"
+          }
+        },
+        "node-pre-gyp": {
+          "version": "0.14.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "detect-libc": "^1.0.2",
+            "mkdirp": "^0.5.1",
+            "needle": "^2.2.1",
+            "nopt": "^4.0.1",
+            "npm-packlist": "^1.1.6",
+            "npmlog": "^4.0.2",
+            "rc": "^1.2.7",
+            "rimraf": "^2.6.1",
+            "semver": "^5.3.0",
+            "tar": "^4.4.2"
+          }
+        },
+        "nopt": {
+          "version": "4.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "abbrev": "1",
+            "osenv": "^0.1.4"
+          }
+        },
+        "npm-bundled": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "npm-normalize-package-bin": "^1.0.1"
+          }
+        },
+        "npm-normalize-package-bin": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "npm-packlist": {
+          "version": "1.4.7",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ignore-walk": "^3.0.1",
+            "npm-bundled": "^1.0.1"
+          }
+        },
+        "npmlog": {
+          "version": "4.1.2",
+          "bundled": true,
+          "dev": 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,
+          "dev": true,
+          "optional": true
+        },
+        "object-assign": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
+        "os-homedir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "os-tmpdir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "osenv": {
+          "version": "0.1.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "os-homedir": "^1.0.0",
+            "os-tmpdir": "^1.0.0"
+          }
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "rc": {
+          "version": "1.2.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "deep-extend": "^0.6.0",
+            "ini": "~1.3.0",
+            "minimist": "^1.2.0",
+            "strip-json-comments": "~2.0.1"
+          },
+          "dependencies": {
+            "minimist": {
+              "version": "1.2.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "bundled": true,
+          "dev": 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.7.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "safer-buffer": {
+          "version": "2.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "sax": {
+          "version": "1.2.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "semver": {
+          "version": "5.7.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "set-blocking": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "signal-exit": {
+          "version": "3.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": 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,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "tar": {
+          "version": "4.4.13",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chownr": "^1.1.1",
+            "fs-minipass": "^1.2.5",
+            "minipass": "^2.8.6",
+            "minizlib": "^1.2.1",
+            "mkdirp": "^0.5.0",
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.3"
+          }
+        },
+        "util-deprecate": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "wide-align": {
+          "version": "1.1.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "string-width": "^1.0.2 || 2"
+          }
+        },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "yallist": {
+          "version": "3.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
     "function-bind": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
       "requires": {
         "bulk-require": "^1.0.1",
         "htmlparser2": "^3.10.0",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.11",
         "promise": "^8.0.2"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         },
         "promise": {
           "version": "8.0.3",
           }
         },
         "mem": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+          "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
           "requires": {
             "map-age-cleaner": "^0.1.1",
             "mimic-fn": "^2.0.0",
             "p-is-promise": "^2.0.0"
-          },
-          "version": "4.3.0"
+          }
         },
         "mimic-fn": {
           "version": "2.1.0",
           "requires": {
             "execa": "^1.0.0",
             "lcid": "^2.0.0",
-            "mem": "4.3.0"
+            "mem": "^4.0.0"
           },
           "dependencies": {
             "mem": {
-              "version": "4.3.0"
+              "version": "4.3.0",
+              "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+              "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+              "dev": true,
+              "requires": {
+                "map-age-cleaner": "^0.1.1",
+                "mimic-fn": "^2.0.0",
+                "p-is-promise": "^2.0.0"
+              }
             }
           }
         },
       "requires": {
         "http-proxy": "^1.17.0",
         "is-glob": "^4.0.0",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.11",
         "micromatch": "^3.1.10"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
         "cli-width": "^2.0.0",
         "external-editor": "^3.0.3",
         "figures": "^3.0.0",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.15",
         "mute-stream": "0.0.8",
         "run-async": "^2.2.0",
         "rxjs": "^6.4.0",
           "dev": true
         },
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         },
         "string-width": {
           "version": "4.2.0",
       "integrity": "sha1-5dguaimiX2YsZA5MMnDC+acTh+c=",
       "dev": true,
       "requires": {
-        "lodash": "4.17.15"
+        "lodash": "3.10.0"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "3.10.0",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.0.tgz",
+          "integrity": "sha1-k9UcZygopEFqEq9XIguoqHN+L7s=",
+          "dev": true
         }
       }
     },
         "@jest/types": "^24.9.0",
         "anymatch": "^2.0.0",
         "fb-watchman": "^2.0.0",
-        "fsevents": "2.1.2",
+        "fsevents": "^1.2.7",
         "graceful-fs": "^4.1.15",
         "invariant": "^2.2.4",
         "jest-serializer": "^24.9.0",
             "normalize-path": "^2.1.1"
           }
         },
-        "fsevents": {
-          "version": "2.1.2"
-        },
         "normalize-path": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
             "anymatch": "^2.0.0",
             "async-each": "^1.0.1",
             "braces": "^2.3.2",
-            "fsevents": "2.1.2",
+            "fsevents": "^1.2.7",
             "glob-parent": "^3.1.0",
             "inherits": "^2.0.3",
             "is-binary-path": "^1.0.0",
           },
           "dependencies": {
             "fsevents": {
-              "version": "2.1.2"
+              "version": "1.2.11",
+              "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+              "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "bindings": "^1.5.0",
+                "nan": "^2.12.1",
+                "node-pre-gyp": "*"
+              },
+              "dependencies": {
+                "abbrev": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ansi-regex": {
+                  "version": "2.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "aproba": {
+                  "version": "1.2.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "are-we-there-yet": {
+                  "version": "1.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "delegates": "^1.0.0",
+                    "readable-stream": "^2.0.6"
+                  }
+                },
+                "balanced-match": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "brace-expansion": {
+                  "version": "1.1.11",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "balanced-match": "^1.0.0",
+                    "concat-map": "0.0.1"
+                  }
+                },
+                "chownr": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "code-point-at": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "concat-map": {
+                  "version": "0.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "console-control-strings": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "core-util-is": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "debug": {
+                  "version": "3.2.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ms": "^2.1.1"
+                  }
+                },
+                "deep-extend": {
+                  "version": "0.6.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "delegates": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "detect-libc": {
+                  "version": "1.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "fs-minipass": {
+                  "version": "1.2.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.6.0"
+                  }
+                },
+                "fs.realpath": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "gauge": {
+                  "version": "2.7.4",
+                  "bundled": true,
+                  "dev": 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.6",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "iconv-lite": {
+                  "version": "0.4.24",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safer-buffer": ">= 2.1.2 < 3"
+                  }
+                },
+                "ignore-walk": {
+                  "version": "3.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimatch": "^3.0.4"
+                  }
+                },
+                "inflight": {
+                  "version": "1.0.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "once": "^1.3.0",
+                    "wrappy": "1"
+                  }
+                },
+                "inherits": {
+                  "version": "2.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ini": {
+                  "version": "1.3.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "is-fullwidth-code-point": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "number-is-nan": "^1.0.0"
+                  }
+                },
+                "isarray": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minimatch": {
+                  "version": "3.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "brace-expansion": "^1.1.7"
+                  }
+                },
+                "minimist": {
+                  "version": "0.0.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minipass": {
+                  "version": "2.9.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.0"
+                  }
+                },
+                "minizlib": {
+                  "version": "1.3.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.9.0"
+                  }
+                },
+                "mkdirp": {
+                  "version": "0.5.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimist": "0.0.8"
+                  }
+                },
+                "ms": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "needle": {
+                  "version": "2.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "debug": "^3.2.6",
+                    "iconv-lite": "^0.4.4",
+                    "sax": "^1.2.4"
+                  }
+                },
+                "node-pre-gyp": {
+                  "version": "0.14.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "detect-libc": "^1.0.2",
+                    "mkdirp": "^0.5.1",
+                    "needle": "^2.2.1",
+                    "nopt": "^4.0.1",
+                    "npm-packlist": "^1.1.6",
+                    "npmlog": "^4.0.2",
+                    "rc": "^1.2.7",
+                    "rimraf": "^2.6.1",
+                    "semver": "^5.3.0",
+                    "tar": "^4.4.2"
+                  }
+                },
+                "nopt": {
+                  "version": "4.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "abbrev": "1",
+                    "osenv": "^0.1.4"
+                  }
+                },
+                "npm-bundled": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "npm-normalize-package-bin": "^1.0.1"
+                  }
+                },
+                "npm-normalize-package-bin": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "npm-packlist": {
+                  "version": "1.4.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ignore-walk": "^3.0.1",
+                    "npm-bundled": "^1.0.1"
+                  }
+                },
+                "npmlog": {
+                  "version": "4.1.2",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "object-assign": {
+                  "version": "4.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "once": {
+                  "version": "1.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "wrappy": "1"
+                  }
+                },
+                "os-homedir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "os-tmpdir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "osenv": {
+                  "version": "0.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "os-homedir": "^1.0.0",
+                    "os-tmpdir": "^1.0.0"
+                  }
+                },
+                "path-is-absolute": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "process-nextick-args": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "rc": {
+                  "version": "1.2.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "deep-extend": "^0.6.0",
+                    "ini": "~1.3.0",
+                    "minimist": "^1.2.0",
+                    "strip-json-comments": "~2.0.1"
+                  },
+                  "dependencies": {
+                    "minimist": {
+                      "version": "1.2.0",
+                      "bundled": true,
+                      "dev": true,
+                      "optional": true
+                    }
+                  }
+                },
+                "readable-stream": {
+                  "version": "2.3.6",
+                  "bundled": true,
+                  "dev": 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.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "glob": "^7.1.3"
+                  }
+                },
+                "safe-buffer": {
+                  "version": "5.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "safer-buffer": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "sax": {
+                  "version": "1.2.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "semver": {
+                  "version": "5.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "set-blocking": {
+                  "version": "2.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "signal-exit": {
+                  "version": "3.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "string-width": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": 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,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "~5.1.0"
+                  }
+                },
+                "strip-ansi": {
+                  "version": "3.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ansi-regex": "^2.0.0"
+                  }
+                },
+                "strip-json-comments": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "tar": {
+                  "version": "4.4.13",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "chownr": "^1.1.1",
+                    "fs-minipass": "^1.2.5",
+                    "minipass": "^2.8.6",
+                    "minizlib": "^1.2.1",
+                    "mkdirp": "^0.5.0",
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.3"
+                  }
+                },
+                "util-deprecate": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "wide-align": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "string-width": "^1.0.2 || 2"
+                  }
+                },
+                "wrappy": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "yallist": {
+                  "version": "3.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                }
+              }
             }
           }
         },
           }
         },
         "fsevents": {
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "bindings": "^1.5.0",
-            "nan": "^2.12.1",
-            "node-pre-gyp": "*"
-          },
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+          "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
           "dependencies": {
             "abbrev": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "aproba": {
               "version": "1.2.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "are-we-there-yet": {
               "version": "1.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "delegates": "^1.0.0",
             "balanced-match": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "brace-expansion": {
               "version": "1.1.11",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "balanced-match": "^1.0.0",
             "chownr": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "concat-map": {
               "version": "0.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "core-util-is": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "debug": {
               "version": "3.2.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ms": "^2.1.1"
             "deep-extend": {
               "version": "0.6.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "delegates": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "detect-libc": {
               "version": "1.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "fs-minipass": {
               "version": "1.2.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.6.0"
             "fs.realpath": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "gauge": {
               "version": "2.7.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "aproba": "^1.0.3",
             "glob": {
               "version": "7.1.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "fs.realpath": "^1.0.0",
             "has-unicode": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "iconv-lite": {
               "version": "0.4.24",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safer-buffer": ">= 2.1.2 < 3"
             "ignore-walk": {
               "version": "3.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimatch": "^3.0.4"
             "inflight": {
               "version": "1.0.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "once": "^1.3.0",
             "inherits": {
               "version": "2.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ini": {
               "version": "1.3.5",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "is-fullwidth-code-point": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
             "isarray": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minimatch": {
               "version": "3.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "brace-expansion": "^1.1.7"
             "minimist": {
               "version": "0.0.8",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minipass": {
               "version": "2.9.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
             "minizlib": {
               "version": "1.3.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.9.0"
             "mkdirp": {
               "version": "0.5.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimist": "0.0.8"
             "ms": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "needle": {
               "version": "2.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "debug": "^3.2.6",
             "node-pre-gyp": {
               "version": "0.14.0",
               "bundled": true,
-              "dev": true,
-              "optional": true,
               "requires": {
                 "detect-libc": "^1.0.2",
                 "mkdirp": "^0.5.1",
             "nopt": {
               "version": "4.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "abbrev": "1",
             "npm-bundled": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "npm-normalize-package-bin": "^1.0.1"
             "npm-normalize-package-bin": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "npm-packlist": {
               "version": "1.4.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ignore-walk": "^3.0.1",
             "npmlog": {
               "version": "4.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "are-we-there-yet": "~1.1.2",
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "object-assign": {
               "version": "4.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "once": {
               "version": "1.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "wrappy": "1"
             "os-homedir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "os-tmpdir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "osenv": {
               "version": "0.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "os-homedir": "^1.0.0",
             "path-is-absolute": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "process-nextick-args": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "rc": {
               "version": "1.2.8",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "deep-extend": "^0.6.0",
                 "minimist": {
                   "version": "1.2.0",
                   "bundled": true,
-                  "dev": true,
                   "optional": true
                 }
               }
             "readable-stream": {
               "version": "2.3.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "core-util-is": "~1.0.0",
             "rimraf": {
               "version": "2.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "glob": "^7.1.3"
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "safer-buffer": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "sax": {
               "version": "1.2.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "semver": {
               "version": "5.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "set-blocking": {
               "version": "2.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "signal-exit": {
               "version": "3.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "string-width": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
             "string_decoder": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "~5.1.0"
             "strip-ansi": {
               "version": "3.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
             "strip-json-comments": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "tar": {
               "version": "4.4.13",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "chownr": "^1.1.1",
             "util-deprecate": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "wide-align": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "string-width": "^1.0.2 || 2"
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "yallist": {
               "version": "3.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             }
-          },
-          "version": "2.1.2"
+          }
         },
         "is-binary-path": {
           "version": "1.0.1",
       }
     },
     "lodash": {
-      "version": "4.17.15"
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
     },
     "lodash.clonedeep": {
       "version": "4.5.0",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
       "dev": true
     },
+    "mem": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+      "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+      "requires": {
+        "mimic-fn": "^1.0.0"
+      }
+    },
     "memory-fs": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
         "mime-db": "1.43.0"
       }
     },
+    "mimic-fn": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
+    },
     "mini-css-extract-plugin": {
       "version": "0.8.0",
       "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz",
         "tslib": "^1.9.0"
       }
     },
+    "ng-bullet": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/ng-bullet/-/ng-bullet-1.0.3.tgz",
+      "integrity": "sha512-qacsE/w/pLlBxebort1rkrE2B4Vc3idutcpe7tYiHVarz0V6Q5SN8E3d6NUp4UFBMOucpHlCpaASp7qEOsxM1Q==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
     "ng-click-outside": {
       "version": "5.3.0",
       "resolved": "https://registry.npmjs.org/ng-click-outside/-/ng-click-outside-5.3.0.tgz",
       "integrity": "sha512-+WYtu2hSQy0F6VlHOqKhPtdVJimTiXXNtZPBGfLORJNX71ieYGsentke8KG+8EudR36FUB6Ya9g2GwGXM0UqdA=="
     },
+    "ng-mocks": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/ng-mocks/-/ng-mocks-9.0.0.tgz",
+      "integrity": "sha512-YGg7n7F0okLnOFO6ulSXfNWHXx6tlpim2hXC55bGtczLavfUdaCRTOQUOsb37E2l5iOCaMRf2CiFZ8/EEgC1mA==",
+      "dev": true
+    },
     "ng2-charts": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-2.3.0.tgz",
       "integrity": "sha512-D5K7OqF0m5lOBYvNOsraoEo4OPHja9zfGNj+HWy2nUcP0LP2s+Y/QaQlkG/1rHlwXq9HPm8rLxzSutA0eLHxGQ==",
       "requires": {
         "@types/chart.js": "^2.7.48",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.11",
         "tslib": "^1.9.0"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
         }
       }
     },
     "opencollective-postinstall": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz",
-      "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==",
-      "dev": true
+      "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw=="
     },
     "opn": {
       "version": "5.5.0",
       "requires": {
         "execa": "^0.7.0",
         "lcid": "^1.0.0",
-        "mem": "4.3.0"
-      },
-      "dependencies": {
-        "mem": {
-          "version": "4.3.0"
-        },
-        "mimic-fn": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
-        }
+        "mem": "^1.1.0"
       }
     },
     "os-name": {
         "circular-json": "^0.5.1",
         "fs-extra": "^7.0.0",
         "klaw-sync": "^6.0.0",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.11",
         "mkdirp": "^0.5.1",
         "moment": "^2.20.1",
         "q": "^1.5.1",
           }
         },
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         },
         "q": {
           "version": "1.5.1",
       "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
       "dev": true,
       "requires": {
-        "lodash": "4.17.15"
+        "lodash": "^4.17.15"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
             }
           }
         },
-        "binary-extensions": {
-          "version": "1.13.1",
-          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
-          "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
-          "dev": true
-        },
-        "braces": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.1.0",
-            "array-unique": "^0.3.2",
-            "extend-shallow": "^2.0.1",
-            "fill-range": "^4.0.0",
-            "isobject": "^3.0.1",
-            "repeat-element": "^1.1.2",
-            "snapdragon": "^0.8.1",
-            "snapdragon-node": "^2.0.1",
-            "split-string": "^3.0.2",
-            "to-regex": "^3.0.1"
-          }
-        },
-        "chokidar": {
-          "version": "2.1.8",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
-          "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
-          "dev": true,
-          "requires": {
-            "anymatch": "^2.0.0",
-            "async-each": "^1.0.1",
-            "braces": "^2.3.2",
-            "fsevents": "2.1.2",
-            "glob-parent": "^3.1.0",
-            "inherits": "^2.0.3",
-            "is-binary-path": "^1.0.0",
-            "is-glob": "^4.0.0",
-            "normalize-path": "^3.0.0",
-            "path-is-absolute": "^1.0.0",
-            "readdirp": "^2.2.1",
-            "upath": "^1.1.1"
-          },
-          "dependencies": {
-            "fsevents": {
-              "version": "2.1.2"
-            }
-          }
-        },
+        "binary-extensions": {
+          "version": "1.13.1",
+          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+          "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+          "dev": true
+        },
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          }
+        },
+        "chokidar": {
+          "version": "2.1.8",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+          "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+          "dev": true,
+          "requires": {
+            "anymatch": "^2.0.0",
+            "async-each": "^1.0.1",
+            "braces": "^2.3.2",
+            "fsevents": "^1.2.7",
+            "glob-parent": "^3.1.0",
+            "inherits": "^2.0.3",
+            "is-binary-path": "^1.0.0",
+            "is-glob": "^4.0.0",
+            "normalize-path": "^3.0.0",
+            "path-is-absolute": "^1.0.0",
+            "readdirp": "^2.2.1",
+            "upath": "^1.1.1"
+          },
+          "dependencies": {
+            "fsevents": {
+              "version": "1.2.11",
+              "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+              "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "bindings": "^1.5.0",
+                "nan": "^2.12.1",
+                "node-pre-gyp": "*"
+              },
+              "dependencies": {
+                "abbrev": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ansi-regex": {
+                  "version": "2.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "aproba": {
+                  "version": "1.2.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "are-we-there-yet": {
+                  "version": "1.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "delegates": "^1.0.0",
+                    "readable-stream": "^2.0.6"
+                  }
+                },
+                "balanced-match": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "brace-expansion": {
+                  "version": "1.1.11",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "balanced-match": "^1.0.0",
+                    "concat-map": "0.0.1"
+                  }
+                },
+                "chownr": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "code-point-at": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "concat-map": {
+                  "version": "0.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "console-control-strings": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "core-util-is": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "debug": {
+                  "version": "3.2.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ms": "^2.1.1"
+                  }
+                },
+                "deep-extend": {
+                  "version": "0.6.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "delegates": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "detect-libc": {
+                  "version": "1.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "fs-minipass": {
+                  "version": "1.2.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.6.0"
+                  }
+                },
+                "fs.realpath": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "gauge": {
+                  "version": "2.7.4",
+                  "bundled": true,
+                  "dev": 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.6",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "iconv-lite": {
+                  "version": "0.4.24",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safer-buffer": ">= 2.1.2 < 3"
+                  }
+                },
+                "ignore-walk": {
+                  "version": "3.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimatch": "^3.0.4"
+                  }
+                },
+                "inflight": {
+                  "version": "1.0.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "once": "^1.3.0",
+                    "wrappy": "1"
+                  }
+                },
+                "inherits": {
+                  "version": "2.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ini": {
+                  "version": "1.3.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "is-fullwidth-code-point": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "number-is-nan": "^1.0.0"
+                  }
+                },
+                "isarray": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minimatch": {
+                  "version": "3.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "brace-expansion": "^1.1.7"
+                  }
+                },
+                "minimist": {
+                  "version": "0.0.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minipass": {
+                  "version": "2.9.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.0"
+                  }
+                },
+                "minizlib": {
+                  "version": "1.3.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.9.0"
+                  }
+                },
+                "mkdirp": {
+                  "version": "0.5.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimist": "0.0.8"
+                  }
+                },
+                "ms": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "needle": {
+                  "version": "2.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "debug": "^3.2.6",
+                    "iconv-lite": "^0.4.4",
+                    "sax": "^1.2.4"
+                  }
+                },
+                "node-pre-gyp": {
+                  "version": "0.14.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "detect-libc": "^1.0.2",
+                    "mkdirp": "^0.5.1",
+                    "needle": "^2.2.1",
+                    "nopt": "^4.0.1",
+                    "npm-packlist": "^1.1.6",
+                    "npmlog": "^4.0.2",
+                    "rc": "^1.2.7",
+                    "rimraf": "^2.6.1",
+                    "semver": "^5.3.0",
+                    "tar": "^4.4.2"
+                  }
+                },
+                "nopt": {
+                  "version": "4.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "abbrev": "1",
+                    "osenv": "^0.1.4"
+                  }
+                },
+                "npm-bundled": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "npm-normalize-package-bin": "^1.0.1"
+                  }
+                },
+                "npm-normalize-package-bin": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "npm-packlist": {
+                  "version": "1.4.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ignore-walk": "^3.0.1",
+                    "npm-bundled": "^1.0.1"
+                  }
+                },
+                "npmlog": {
+                  "version": "4.1.2",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "object-assign": {
+                  "version": "4.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "once": {
+                  "version": "1.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "wrappy": "1"
+                  }
+                },
+                "os-homedir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "os-tmpdir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "osenv": {
+                  "version": "0.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "os-homedir": "^1.0.0",
+                    "os-tmpdir": "^1.0.0"
+                  }
+                },
+                "path-is-absolute": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "process-nextick-args": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "rc": {
+                  "version": "1.2.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "deep-extend": "^0.6.0",
+                    "ini": "~1.3.0",
+                    "minimist": "^1.2.0",
+                    "strip-json-comments": "~2.0.1"
+                  },
+                  "dependencies": {
+                    "minimist": {
+                      "version": "1.2.0",
+                      "bundled": true,
+                      "dev": true,
+                      "optional": true
+                    }
+                  }
+                },
+                "readable-stream": {
+                  "version": "2.3.6",
+                  "bundled": true,
+                  "dev": 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.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "glob": "^7.1.3"
+                  }
+                },
+                "safe-buffer": {
+                  "version": "5.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "safer-buffer": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "sax": {
+                  "version": "1.2.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "semver": {
+                  "version": "5.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "set-blocking": {
+                  "version": "2.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "signal-exit": {
+                  "version": "3.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "string-width": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": 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,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "~5.1.0"
+                  }
+                },
+                "strip-ansi": {
+                  "version": "3.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ansi-regex": "^2.0.0"
+                  }
+                },
+                "strip-json-comments": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "tar": {
+                  "version": "4.4.13",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "chownr": "^1.1.1",
+                    "fs-minipass": "^1.2.5",
+                    "minipass": "^2.8.6",
+                    "minizlib": "^1.2.1",
+                    "mkdirp": "^0.5.0",
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.3"
+                  }
+                },
+                "util-deprecate": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "wide-align": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "string-width": "^1.0.2 || 2"
+                  }
+                },
+                "wrappy": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "yallist": {
+                  "version": "3.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                }
+              }
+            }
+          }
+        },
         "extend-shallow": {
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
           }
         },
         "fsevents": {
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "bindings": "^1.5.0",
-            "nan": "^2.12.1",
-            "node-pre-gyp": "*"
-          },
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+          "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
           "dependencies": {
             "abbrev": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "aproba": {
               "version": "1.2.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "are-we-there-yet": {
               "version": "1.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "delegates": "^1.0.0",
             "balanced-match": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "brace-expansion": {
               "version": "1.1.11",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "balanced-match": "^1.0.0",
             "chownr": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "concat-map": {
               "version": "0.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "core-util-is": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "debug": {
               "version": "3.2.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ms": "^2.1.1"
             "deep-extend": {
               "version": "0.6.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "delegates": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "detect-libc": {
               "version": "1.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "fs-minipass": {
               "version": "1.2.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.6.0"
             "fs.realpath": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "gauge": {
               "version": "2.7.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "aproba": "^1.0.3",
             "glob": {
               "version": "7.1.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "fs.realpath": "^1.0.0",
             "has-unicode": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "iconv-lite": {
               "version": "0.4.24",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safer-buffer": ">= 2.1.2 < 3"
             "ignore-walk": {
               "version": "3.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimatch": "^3.0.4"
             "inflight": {
               "version": "1.0.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "once": "^1.3.0",
             "inherits": {
               "version": "2.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ini": {
               "version": "1.3.5",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "is-fullwidth-code-point": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
             "isarray": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minimatch": {
               "version": "3.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "brace-expansion": "^1.1.7"
             "minimist": {
               "version": "0.0.8",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minipass": {
               "version": "2.9.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
             "minizlib": {
               "version": "1.3.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.9.0"
             "mkdirp": {
               "version": "0.5.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimist": "0.0.8"
             "ms": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "needle": {
               "version": "2.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "debug": "^3.2.6",
             "node-pre-gyp": {
               "version": "0.14.0",
               "bundled": true,
-              "dev": true,
-              "optional": true,
               "requires": {
                 "detect-libc": "^1.0.2",
                 "mkdirp": "^0.5.1",
             "nopt": {
               "version": "4.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "abbrev": "1",
             "npm-bundled": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "npm-normalize-package-bin": "^1.0.1"
             "npm-normalize-package-bin": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "npm-packlist": {
               "version": "1.4.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ignore-walk": "^3.0.1",
             "npmlog": {
               "version": "4.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "are-we-there-yet": "~1.1.2",
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "object-assign": {
               "version": "4.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "once": {
               "version": "1.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "wrappy": "1"
             "os-homedir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "os-tmpdir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "osenv": {
               "version": "0.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "os-homedir": "^1.0.0",
             "path-is-absolute": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "process-nextick-args": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "rc": {
               "version": "1.2.8",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "deep-extend": "^0.6.0",
                 "minimist": {
                   "version": "1.2.0",
                   "bundled": true,
-                  "dev": true,
                   "optional": true
                 }
               }
             "readable-stream": {
               "version": "2.3.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "core-util-is": "~1.0.0",
             "rimraf": {
               "version": "2.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "glob": "^7.1.3"
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "safer-buffer": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "sax": {
               "version": "1.2.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "semver": {
               "version": "5.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "set-blocking": {
               "version": "2.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "signal-exit": {
               "version": "3.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "string-width": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
             "string_decoder": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "~5.1.0"
             "strip-ansi": {
               "version": "3.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
             "strip-json-comments": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "tar": {
               "version": "4.4.13",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "chownr": "^1.1.1",
             "util-deprecate": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "wide-align": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "string-width": "^1.0.2 || 2"
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "yallist": {
               "version": "3.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             }
-          },
-          "version": "2.1.2"
+          }
         },
         "is-binary-path": {
           "version": "1.0.1",
             }
           }
         },
-        "binary-extensions": {
-          "version": "1.13.1",
-          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
-          "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
-          "dev": true
-        },
-        "braces": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.1.0",
-            "array-unique": "^0.3.2",
-            "extend-shallow": "^2.0.1",
-            "fill-range": "^4.0.0",
-            "isobject": "^3.0.1",
-            "repeat-element": "^1.1.2",
-            "snapdragon": "^0.8.1",
-            "snapdragon-node": "^2.0.1",
-            "split-string": "^3.0.2",
-            "to-regex": "^3.0.1"
-          }
-        },
-        "camelcase": {
-          "version": "5.3.1",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
-          "dev": true
-        },
-        "chokidar": {
-          "version": "2.1.8",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
-          "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
-          "dev": true,
-          "requires": {
-            "anymatch": "^2.0.0",
-            "async-each": "^1.0.1",
-            "braces": "^2.3.2",
-            "fsevents": "2.1.2",
-            "glob-parent": "^3.1.0",
-            "inherits": "^2.0.3",
-            "is-binary-path": "^1.0.0",
-            "is-glob": "^4.0.0",
-            "normalize-path": "^3.0.0",
-            "path-is-absolute": "^1.0.0",
-            "readdirp": "^2.2.1",
-            "upath": "^1.1.1"
-          },
-          "dependencies": {
-            "fsevents": {
-              "version": "2.1.2"
-            }
-          }
-        },
+        "binary-extensions": {
+          "version": "1.13.1",
+          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+          "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+          "dev": true
+        },
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          }
+        },
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+          "dev": true
+        },
+        "chokidar": {
+          "version": "2.1.8",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+          "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+          "dev": true,
+          "requires": {
+            "anymatch": "^2.0.0",
+            "async-each": "^1.0.1",
+            "braces": "^2.3.2",
+            "fsevents": "^1.2.7",
+            "glob-parent": "^3.1.0",
+            "inherits": "^2.0.3",
+            "is-binary-path": "^1.0.0",
+            "is-glob": "^4.0.0",
+            "normalize-path": "^3.0.0",
+            "path-is-absolute": "^1.0.0",
+            "readdirp": "^2.2.1",
+            "upath": "^1.1.1"
+          },
+          "dependencies": {
+            "fsevents": {
+              "version": "1.2.11",
+              "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+              "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "bindings": "^1.5.0",
+                "nan": "^2.12.1",
+                "node-pre-gyp": "*"
+              },
+              "dependencies": {
+                "abbrev": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ansi-regex": {
+                  "version": "2.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "aproba": {
+                  "version": "1.2.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "are-we-there-yet": {
+                  "version": "1.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "delegates": "^1.0.0",
+                    "readable-stream": "^2.0.6"
+                  }
+                },
+                "balanced-match": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "brace-expansion": {
+                  "version": "1.1.11",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "balanced-match": "^1.0.0",
+                    "concat-map": "0.0.1"
+                  }
+                },
+                "chownr": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "code-point-at": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "concat-map": {
+                  "version": "0.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "console-control-strings": {
+                  "version": "1.1.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "core-util-is": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "debug": {
+                  "version": "3.2.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ms": "^2.1.1"
+                  }
+                },
+                "deep-extend": {
+                  "version": "0.6.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "delegates": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "detect-libc": {
+                  "version": "1.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "fs-minipass": {
+                  "version": "1.2.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.6.0"
+                  }
+                },
+                "fs.realpath": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "gauge": {
+                  "version": "2.7.4",
+                  "bundled": true,
+                  "dev": 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.6",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "iconv-lite": {
+                  "version": "0.4.24",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safer-buffer": ">= 2.1.2 < 3"
+                  }
+                },
+                "ignore-walk": {
+                  "version": "3.0.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimatch": "^3.0.4"
+                  }
+                },
+                "inflight": {
+                  "version": "1.0.6",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "once": "^1.3.0",
+                    "wrappy": "1"
+                  }
+                },
+                "inherits": {
+                  "version": "2.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "ini": {
+                  "version": "1.3.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "is-fullwidth-code-point": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "number-is-nan": "^1.0.0"
+                  }
+                },
+                "isarray": {
+                  "version": "1.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minimatch": {
+                  "version": "3.0.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "brace-expansion": "^1.1.7"
+                  }
+                },
+                "minimist": {
+                  "version": "0.0.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "minipass": {
+                  "version": "2.9.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.0"
+                  }
+                },
+                "minizlib": {
+                  "version": "1.3.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minipass": "^2.9.0"
+                  }
+                },
+                "mkdirp": {
+                  "version": "0.5.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "minimist": "0.0.8"
+                  }
+                },
+                "ms": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "needle": {
+                  "version": "2.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "debug": "^3.2.6",
+                    "iconv-lite": "^0.4.4",
+                    "sax": "^1.2.4"
+                  }
+                },
+                "node-pre-gyp": {
+                  "version": "0.14.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "detect-libc": "^1.0.2",
+                    "mkdirp": "^0.5.1",
+                    "needle": "^2.2.1",
+                    "nopt": "^4.0.1",
+                    "npm-packlist": "^1.1.6",
+                    "npmlog": "^4.0.2",
+                    "rc": "^1.2.7",
+                    "rimraf": "^2.6.1",
+                    "semver": "^5.3.0",
+                    "tar": "^4.4.2"
+                  }
+                },
+                "nopt": {
+                  "version": "4.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "abbrev": "1",
+                    "osenv": "^0.1.4"
+                  }
+                },
+                "npm-bundled": {
+                  "version": "1.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "npm-normalize-package-bin": "^1.0.1"
+                  }
+                },
+                "npm-normalize-package-bin": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "npm-packlist": {
+                  "version": "1.4.7",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ignore-walk": "^3.0.1",
+                    "npm-bundled": "^1.0.1"
+                  }
+                },
+                "npmlog": {
+                  "version": "4.1.2",
+                  "bundled": true,
+                  "dev": 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,
+                  "dev": true,
+                  "optional": true
+                },
+                "object-assign": {
+                  "version": "4.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "once": {
+                  "version": "1.4.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "wrappy": "1"
+                  }
+                },
+                "os-homedir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "os-tmpdir": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "osenv": {
+                  "version": "0.1.5",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "os-homedir": "^1.0.0",
+                    "os-tmpdir": "^1.0.0"
+                  }
+                },
+                "path-is-absolute": {
+                  "version": "1.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "process-nextick-args": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "rc": {
+                  "version": "1.2.8",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "deep-extend": "^0.6.0",
+                    "ini": "~1.3.0",
+                    "minimist": "^1.2.0",
+                    "strip-json-comments": "~2.0.1"
+                  },
+                  "dependencies": {
+                    "minimist": {
+                      "version": "1.2.0",
+                      "bundled": true,
+                      "dev": true,
+                      "optional": true
+                    }
+                  }
+                },
+                "readable-stream": {
+                  "version": "2.3.6",
+                  "bundled": true,
+                  "dev": 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.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "glob": "^7.1.3"
+                  }
+                },
+                "safe-buffer": {
+                  "version": "5.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "safer-buffer": {
+                  "version": "2.1.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "sax": {
+                  "version": "1.2.4",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "semver": {
+                  "version": "5.7.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "set-blocking": {
+                  "version": "2.0.0",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "signal-exit": {
+                  "version": "3.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "string-width": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": 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,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "safe-buffer": "~5.1.0"
+                  }
+                },
+                "strip-ansi": {
+                  "version": "3.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "ansi-regex": "^2.0.0"
+                  }
+                },
+                "strip-json-comments": {
+                  "version": "2.0.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "tar": {
+                  "version": "4.4.13",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "chownr": "^1.1.1",
+                    "fs-minipass": "^1.2.5",
+                    "minipass": "^2.8.6",
+                    "minizlib": "^1.2.1",
+                    "mkdirp": "^0.5.0",
+                    "safe-buffer": "^5.1.2",
+                    "yallist": "^3.0.3"
+                  }
+                },
+                "util-deprecate": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "wide-align": {
+                  "version": "1.1.3",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true,
+                  "requires": {
+                    "string-width": "^1.0.2 || 2"
+                  }
+                },
+                "wrappy": {
+                  "version": "1.0.2",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                },
+                "yallist": {
+                  "version": "3.1.1",
+                  "bundled": true,
+                  "dev": true,
+                  "optional": true
+                }
+              }
+            }
+          }
+        },
         "cliui": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
           }
         },
         "fsevents": {
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "bindings": "^1.5.0",
-            "nan": "^2.12.1",
-            "node-pre-gyp": "*"
-          },
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
+          "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
           "dependencies": {
             "abbrev": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "aproba": {
               "version": "1.2.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "are-we-there-yet": {
               "version": "1.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "delegates": "^1.0.0",
             "balanced-match": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "brace-expansion": {
               "version": "1.1.11",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "balanced-match": "^1.0.0",
             "chownr": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "concat-map": {
               "version": "0.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "core-util-is": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "debug": {
               "version": "3.2.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ms": "^2.1.1"
             "deep-extend": {
               "version": "0.6.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "delegates": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "detect-libc": {
               "version": "1.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "fs-minipass": {
               "version": "1.2.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.6.0"
             "fs.realpath": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "gauge": {
               "version": "2.7.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "aproba": "^1.0.3",
             "glob": {
               "version": "7.1.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "fs.realpath": "^1.0.0",
             "has-unicode": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "iconv-lite": {
               "version": "0.4.24",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safer-buffer": ">= 2.1.2 < 3"
             "ignore-walk": {
               "version": "3.0.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimatch": "^3.0.4"
             "inflight": {
               "version": "1.0.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "once": "^1.3.0",
             "inherits": {
               "version": "2.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "ini": {
               "version": "1.3.5",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "is-fullwidth-code-point": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
             "isarray": {
               "version": "1.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minimatch": {
               "version": "3.0.4",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "brace-expansion": "^1.1.7"
             "minimist": {
               "version": "0.0.8",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "minipass": {
               "version": "2.9.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
             "minizlib": {
               "version": "1.3.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minipass": "^2.9.0"
             "mkdirp": {
               "version": "0.5.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "minimist": "0.0.8"
             "ms": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "needle": {
               "version": "2.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "debug": "^3.2.6",
             "node-pre-gyp": {
               "version": "0.14.0",
               "bundled": true,
-              "dev": true,
-              "optional": true,
               "requires": {
                 "detect-libc": "^1.0.2",
                 "mkdirp": "^0.5.1",
             "nopt": {
               "version": "4.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "abbrev": "1",
             "npm-bundled": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "npm-normalize-package-bin": "^1.0.1"
             "npm-normalize-package-bin": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "npm-packlist": {
               "version": "1.4.7",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ignore-walk": "^3.0.1",
             "npmlog": {
               "version": "4.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "are-we-there-yet": "~1.1.2",
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "object-assign": {
               "version": "4.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "once": {
               "version": "1.4.0",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "wrappy": "1"
             "os-homedir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "os-tmpdir": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "osenv": {
               "version": "0.1.5",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "os-homedir": "^1.0.0",
             "path-is-absolute": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "process-nextick-args": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "rc": {
               "version": "1.2.8",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "deep-extend": "^0.6.0",
                 "minimist": {
                   "version": "1.2.0",
                   "bundled": true,
-                  "dev": true,
                   "optional": true
                 }
               }
             "readable-stream": {
               "version": "2.3.6",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "core-util-is": "~1.0.0",
             "rimraf": {
               "version": "2.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "glob": "^7.1.3"
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "safer-buffer": {
               "version": "2.1.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "sax": {
               "version": "1.2.4",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "semver": {
               "version": "5.7.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "set-blocking": {
               "version": "2.0.0",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "signal-exit": {
               "version": "3.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "string-width": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
             "string_decoder": {
               "version": "1.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "safe-buffer": "~5.1.0"
             "strip-ansi": {
               "version": "3.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
             "strip-json-comments": {
               "version": "2.0.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "tar": {
               "version": "4.4.13",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "chownr": "^1.1.1",
             "util-deprecate": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "wide-align": {
               "version": "1.1.3",
               "bundled": true,
-              "dev": true,
               "optional": true,
               "requires": {
                 "string-width": "^1.0.2 || 2"
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
               "optional": true
             },
             "yallist": {
               "version": "3.1.1",
               "bundled": true,
-              "dev": true,
               "optional": true
             }
-          },
-          "version": "2.1.2"
+          }
         },
         "get-stream": {
           "version": "4.1.0",
           }
         },
         "mem": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+          "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
           "requires": {
             "map-age-cleaner": "^0.1.1",
             "mimic-fn": "^2.0.0",
             "p-is-promise": "^2.0.0"
-          },
-          "version": "4.3.0"
+          }
         },
         "mimic-fn": {
           "version": "2.1.0",
           "requires": {
             "execa": "^1.0.0",
             "lcid": "^2.0.0",
-            "mem": "4.3.0"
+            "mem": "^4.0.0"
           },
           "dependencies": {
             "mem": {
-              "version": "4.3.0"
+              "version": "4.3.0",
+              "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+              "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+              "dev": true,
+              "requires": {
+                "map-age-cleaner": "^0.1.1",
+                "mimic-fn": "^2.0.0",
+                "p-is-promise": "^2.0.0"
+              }
             }
           }
         },
       "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==",
       "dev": true,
       "requires": {
-        "lodash": "4.17.15"
+        "lodash": "^4.17.5"
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.15"
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+          "dev": true
         }
       }
     },
       "integrity": "sha512-GkPiJL8jifSrKReKaTZ5jkhrMEgXbXYC+IPo1iquBjayRa0q86w3Dipjn8b415jpitMExe9lV8iTsv8tk3DGag=="
     }
   }
-}
\ No newline at end of file
+}
index b5100ffd3b89cfce17b68e62c5c0b0066404cc0e..f5ff62dfecbb2073133c8b7389764e2817f62be9 100644 (file)
     "jest-canvas-mock": "2.2.0",
     "jest-preset-angular": "8.0.0",
     "jest-silent-reporter": "0.1.2",
+    "ng-bullet": "^1.0.3",
+    "ng-mocks": "^9.0.0",
     "npm-force-resolutions": "0.0.3",
     "npm-run-all": "4.1.5",
     "prettier": "1.18.2",
index 1b94b3d9be877ed296c0112a473a47bfcfa878b1..24fdf9ea8f11b4502a062fd3c2403a04fe8d1340 100644 (file)
@@ -259,7 +259,7 @@ const routes: Routes = [
       },
       {
         path: 'nfs',
-        canActivateChild: [ModuleStatusGuardService],
+        canActivateChild: [FeatureTogglesGuardService, ModuleStatusGuardService],
         data: {
           moduleStatusGuardConfig: {
             apiPath: 'nfs-ganesha',
index 1b1b90511613f226edcf4b0f64f43e072cf34b44..d05e2669925f551134b09ff869e004834db45cd9 100644 (file)
   </li>
 </ng-template>
 
-<ng-template #cd_menu>
-  <!-- Dashboard -->
-  <li routerLinkActive="active"
-      class="nav-item tc_menuitem_dashboard">
-    <a routerLink="/dashboard"
-       class="nav-link">
-      <span i18n>Dashboard</span>&nbsp;
-      <i [ngClass]="[icons.health]"
-         [ngStyle]="summaryData?.health_status | healthColor"></i>
-    </a>
-  </li>
+<ng-template #cd_menu >
+  <ng-container *ngIf="enabledFeature$ | async as enabledFeature">
+    <!-- Dashboard -->
+    <li routerLinkActive="active"
+        class="nav-item tc_menuitem_dashboard">
+      <a routerLink="/dashboard"
+         class="nav-link">
+        <span i18n>Dashboard</span>&nbsp;
+        <i [ngClass]="[icons.health]"
+           [ngStyle]="summaryData?.health_status | healthColor"></i>
+      </a>
+    </li>
 
-  <!-- Cluster -->
-  <li routerLinkActive="active"
-      class="nav-item tc_menuitem_cluster"
-      *ngIf="permissions.hosts.read ||permissions.monitor.read || permissions.osd.read || permissions.configOpt.read">
-    <a (click)="toggleSubMenu('cluster')"
-       class="nav-link dropdown-toggle"
-       [attr.aria-expanded]="displayedSubMenu == 'cluster'"
-       aria-controls="collapseBasic">
-      <ng-container i18n>Cluster</ng-container>
-    </a>
-    <ul class="list-unstyled"
-        [collapse]="displayedSubMenu !== 'cluster'"
-        [isAnimated]="true">
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_hosts"
-          *ngIf="permissions.hosts.read">
-        <a i18n
-           routerLink="/hosts">Hosts</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_cluster_inventory"
-          *ngIf="permissions.hosts.read">
-        <a i18n
-           routerLink="/inventory">Inventory</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_cluster_monitor"
-          *ngIf="permissions.monitor.read">
-        <a i18n
-           routerLink="/monitor/">Monitors</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_cluster_services"
-          *ngIf="permissions.hosts.read">
-        <a i18n
-           routerLink="/services/">Services</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_hosts"
-          *ngIf="permissions.osd.read">
-        <a i18n
-           routerLink="/osd">OSDs</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_configuration"
-          *ngIf="permissions.configOpt.read">
-        <a i18n
-           routerLink="/configuration">Configuration</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_crush"
-          *ngIf="permissions.hosts.read && permissions.osd.read">
-        <a i18n
-           routerLink="/crush-map">CRUSH map</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_modules"
-          *ngIf="permissions.configOpt.read">
-        <a i18n
-           routerLink="/mgr-modules">Manager modules</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_log"
-          *ngIf="permissions.log.read">
-        <a i18n
-           routerLink="/logs">Logs</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_monitoring"
-          *ngIf="(isAlertmanagerConfigured || isPrometheusConfigured) && permissions.prometheus.read">
-        <a i18n
-           routerLink="/monitoring">Monitoring</a>
-      </li>
-    </ul>
-  </li>
+    <!-- Cluster -->
+    <li routerLinkActive="active"
+        class="nav-item tc_menuitem_cluster"
+        *ngIf="permissions.hosts.read || permissions.monitor.read ||
+        permissions.osd.read || permissions.configOpt.read ||
+        permissions.log.read || permissions.prometheus.read">
+      <a (click)="toggleSubMenu('cluster')"
+         class="nav-link dropdown-toggle"
+         [attr.aria-expanded]="displayedSubMenu == 'cluster'"
+         aria-controls="collapseBasic">
+        <ng-container i18n>Cluster</ng-container>
+      </a>
+      <ul class="list-unstyled"
+          [collapse]="displayedSubMenu !== 'cluster'"
+          [isAnimated]="true">
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_hosts"
+            *ngIf="permissions.hosts.read">
+          <a i18n
+             routerLink="/hosts">Hosts</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_cluster_inventory"
+            *ngIf="permissions.hosts.read">
+          <a i18n
+             routerLink="/inventory">Inventory</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_cluster_monitor"
+            *ngIf="permissions.monitor.read">
+          <a i18n
+             routerLink="/monitor/">Monitors</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_cluster_services"
+            *ngIf="permissions.hosts.read">
+          <a i18n
+             routerLink="/services/">Services</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_osds"
+            *ngIf="permissions.osd.read">
+          <a i18n
+             routerLink="/osd">OSDs</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_configuration"
+            *ngIf="permissions.configOpt.read">
+          <a i18n
+             routerLink="/configuration">Configuration</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_crush"
+            *ngIf="permissions.osd.read">
+          <a i18n
+             routerLink="/crush-map">CRUSH map</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_modules"
+            *ngIf="permissions.configOpt.read">
+          <a i18n
+             routerLink="/mgr-modules">Manager modules</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_log"
+            *ngIf="permissions.log.read">
+          <a i18n
+             routerLink="/logs">Logs</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_monitoring"
+            *ngIf="permissions.prometheus.read">
+          <a i18n
+             routerLink="/monitoring">Monitoring</a>
+        </li>
+      </ul>
+    </li>
 
-  <!-- Pools -->
-  <li routerLinkActive="active"
-      class="nav-item tc_menuitem_pool"
-      *ngIf="permissions.pool.read">
-    <a class="nav-link"
-       i18n
-       routerLink="/pool">Pools</a>
-  </li>
+    <!-- Pools -->
+    <li routerLinkActive="active"
+        class="nav-item tc_menuitem_pool"
+        *ngIf="permissions.pool.read">
+      <a class="nav-link"
+         i18n
+         routerLink="/pool">Pools</a>
+    </li>
 
-  <!-- Block -->
-  <li routerLinkActive="active"
-      class="nav-item tc_menuitem_block"
-      *ngIf="permissions.rbdImage.read || permissions.rbdMirroring.read || permissions.iscsi.read">
-    <a class="nav-link dropdown-toggle"
-       (click)="toggleSubMenu('block')"
-       [attr.aria-expanded]="displayedSubMenu == 'block'"
-       aria-controls="collapseBasic"
-       [ngStyle]="blockHealthColor()">
-      <ng-container i18n>Block</ng-container>
-    </a>
+    <!-- Block -->
+    <li routerLinkActive="active"
+        class="nav-item tc_menuitem_block"
+        *ngIf="(permissions.rbdImage.read || permissions.rbdMirroring.read || permissions.iscsi.read) &&
+        (enabledFeature.rbd || enabledFeature.mirroring || enabledFeature.iscsi)">
+      <a class="nav-link dropdown-toggle"
+         (click)="toggleSubMenu('block')"
+         [attr.aria-expanded]="displayedSubMenu == 'block'"
+         aria-controls="collapseBasic"
+         [ngStyle]="blockHealthColor()">
+        <ng-container i18n>Block</ng-container>
+      </a>
 
-    <ul class="list-unstyled"
-        [collapse]="displayedSubMenu !== 'block'"
-        [isAnimated]="true">
-      <li routerLinkActive="active"
-          *ngIf="permissions.rbdImage.read">
-        <a i18n
-           routerLink="/block/rbd">Images</a>
-      </li>
+      <ul class="list-unstyled"
+          [collapse]="displayedSubMenu !== 'block'"
+          [isAnimated]="true">
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_block_images"
+            *ngIf="permissions.rbdImage.read && enabledFeature.rbd">
+          <a i18n
+             routerLink="/block/rbd">Images</a>
+        </li>
 
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_block_mirroring"
-          *ngIf="permissions.rbdMirroring.read">
-        <a routerLink="/block/mirroring">
-          <ng-container i18n>Mirroring</ng-container>
-          <small *ngIf="summaryData?.rbd_mirroring?.warnings !== 0"
-                 class="badge badge-warning">{{ summaryData?.rbd_mirroring?.warnings }}</small>
-          <small *ngIf="summaryData?.rbd_mirroring?.errors !== 0"
-                 class="badge badge-danger">{{ summaryData?.rbd_mirroring?.errors }}</small>
-        </a>
-      </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_block_mirroring"
+            *ngIf="permissions.rbdMirroring.read && enabledFeature.mirroring">
+          <a routerLink="/block/mirroring">
+            <ng-container i18n>Mirroring</ng-container>
+            <small *ngIf="summaryData?.rbd_mirroring?.warnings !== 0"
+                   class="badge badge-warning">{{ summaryData?.rbd_mirroring?.warnings }}</small>
+            <small *ngIf="summaryData?.rbd_mirroring?.errors !== 0"
+                   class="badge badge-danger">{{ summaryData?.rbd_mirroring?.errors }}</small>
+          </a>
+        </li>
 
-      <li routerLinkActive="active"
-          *ngIf="permissions.iscsi.read">
-        <a i18n
-           routerLink="/block/iscsi">iSCSI</a>
-      </li>
-    </ul>
-  </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_block_iscsi"
+            *ngIf="permissions.iscsi.read && enabledFeature.iscsi">
+          <a i18n
+             routerLink="/block/iscsi">iSCSI</a>
+        </li>
+      </ul>
+    </li>
 
-  <!-- NFS -->
-  <li routerLinkActive="active"
-      class="item tc_menuitem_nfs"
-      *ngIf="permissions?.nfs?.read">
-    <a i18n
-       class="nav-link"
-       routerLink="/nfs">NFS</a>
-  </li>
+    <!-- NFS -->
+    <li routerLinkActive="active"
+        class="nav-item tc_menuitem_nfs"
+        *ngIf="permissions.nfs.read && enabledFeature.nfs">
+      <a i18n
+         class="nav-link"
+         routerLink="/nfs">NFS</a>
+    </li>
 
-  <!-- Filesystem -->
-  <li routerLinkActive="active"
-      class="nav-item tc_menuitem_cephs"
-      *ngIf="permissions.cephfs.read">
-    <a i18n
-       class="nav-link"
-       routerLink="/cephfs">Filesystems</a>
-  </li>
+    <!-- Filesystem -->
+    <li routerLinkActive="active"
+        class="nav-item tc_menuitem_cephfs"
+        *ngIf="permissions.cephfs.read && enabledFeature.cephfs">
+      <a i18n
+         class="nav-link"
+         routerLink="/cephfs">Filesystems</a>
+    </li>
 
-  <!-- Object Gateway -->
-  <li routerLinkActive="active"
-      class="nav-item tc_menuitem_rgw"
-      *ngIf="permissions.rgw.read">
-    <a class="nav-link dropdown-toggle"
-       (click)="toggleSubMenu('rgw')"
-       [attr.aria-expanded]="displayedSubMenu == 'rgw'"
-       aria-controls="collapseBasic">
-      <ng-container i18n>Object Gateway</ng-container>
-    </a>
-    <ul class="list-unstyled"
-        [collapse]="displayedSubMenu !== 'rgw'"
-        [isAnimated]="true">
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_rgw_daemons">
-        <a i18n
-           routerLink="/rgw/daemon">Daemons</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_rgw_users">
-        <a i18n
-           routerLink="/rgw/user">Users</a>
-      </li>
-      <li routerLinkActive="active"
-          class="tc_submenuitem tc_submenuitem_rgw_buckets">
-        <a i18n
-           routerLink="/rgw/bucket">Buckets</a>
-      </li>
-    </ul>
-  </li>
+    <!-- Object Gateway -->
+    <li routerLinkActive="active"
+        class="nav-item tc_menuitem_rgw"
+        *ngIf="permissions.rgw.read && enabledFeature.rgw">
+      <a class="nav-link dropdown-toggle"
+         (click)="toggleSubMenu('rgw')"
+         [attr.aria-expanded]="displayedSubMenu == 'rgw'"
+         aria-controls="collapseBasic">
+        <ng-container i18n>Object Gateway</ng-container>
+      </a>
+      <ul class="list-unstyled"
+          [collapse]="displayedSubMenu !== 'rgw'"
+          [isAnimated]="true">
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_rgw_daemons">
+          <a i18n
+             routerLink="/rgw/daemon">Daemons</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_rgw_users">
+          <a i18n
+             routerLink="/rgw/user">Users</a>
+        </li>
+        <li routerLinkActive="active"
+            class="tc_submenuitem tc_submenuitem_rgw_buckets">
+          <a i18n
+             routerLink="/rgw/bucket">Buckets</a>
+        </li>
+      </ul>
+    </li>
+  </ng-container>
 </ng-template>
index da1e780e9a63ebf304871127d63767c910935ea7..fe4dec40e2b982f5cbfd45734f3811df6c61a93b 100644 (file)
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
 
-import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
-import { AppModule } from '../../../app.module';
-import { PrometheusService } from '../../../shared/api/prometheus.service';
-import { Permissions } from '../../../shared/models/permissions';
+import { configureTestSuite } from 'ng-bullet';
+import { MockModule } from 'ng-mocks';
+import { of } from 'rxjs';
+
+import { Permission, Permissions } from '../../../shared/models/permissions';
 import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import {
+  Features,
+  FeatureTogglesMap,
+  FeatureTogglesService
+} from '../../../shared/services/feature-toggles.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { NavigationModule } from '../navigation.module';
 import { NavigationComponent } from './navigation.component';
 
+function everythingPermittedExcept(disabledPermissions: string[] = []): any {
+  const permissions: Permissions = new Permissions({});
+  Object.keys(permissions).forEach(
+    (key) => (permissions[key] = new Permission(disabledPermissions.includes(key) ? [] : ['read']))
+  );
+  return permissions;
+}
+
+function onlyPermitted(enabledPermissions: string[] = []): any {
+  const permissions: Permissions = new Permissions({});
+  enabledPermissions.forEach((key) => (permissions[key] = new Permission(['read'])));
+  return permissions;
+}
+
+function everythingEnabledExcept(features: Features[] = []): FeatureTogglesMap {
+  const featureTogglesMap: FeatureTogglesMap = new FeatureTogglesMap();
+  features.forEach((key) => (featureTogglesMap[key] = false));
+  return featureTogglesMap;
+}
+
+function onlyEnabled(features: Features[] = []): FeatureTogglesMap {
+  const featureTogglesMap: FeatureTogglesMap = new FeatureTogglesMap();
+  Object.keys(featureTogglesMap).forEach(
+    (key) => (featureTogglesMap[key] = features.includes(<Features>key))
+  );
+  return featureTogglesMap;
+}
+
 describe('NavigationComponent', () => {
   let component: NavigationComponent;
   let fixture: ComponentFixture<NavigationComponent>;
-  let ifAlertmanagerConfiguredSpy: jasmine.Spy;
-  let ifPrometheusConfigured: jasmine.Spy;
 
-  configureTestBed({
-    imports: [AppModule],
-    providers: i18nProviders
+  configureTestSuite(() => {
+    TestBed.configureTestingModule({
+      declarations: [NavigationComponent],
+      imports: [MockModule(NavigationModule)],
+      providers: [
+        {
+          provide: AuthStorageService,
+          useValue: {
+            getPermissions: jest.fn(),
+            isPwdDisplayed$: { subscribe: jest.fn() }
+          }
+        },
+        { provide: SummaryService, useValue: { subscribe: jest.fn() } },
+        { provide: FeatureTogglesService, useValue: { get: jest.fn() } }
+      ]
+    });
   });
 
   beforeEach(() => {
-    ifAlertmanagerConfiguredSpy = spyOn(
-      TestBed.get(PrometheusService),
-      'ifAlertmanagerConfigured'
-    ).and.stub();
-    ifPrometheusConfigured = spyOn(
-      TestBed.get(PrometheusService),
-      'ifPrometheusConfigured'
-    ).and.stub();
     fixture = TestBed.createComponent(NavigationComponent);
     component = fixture.componentInstance;
-    fixture.detectChanges();
   });
 
-  it('should create and PrometheusService methods should not have been called', () => {
-    expect(component).toBeTruthy();
-    expect(ifAlertmanagerConfiguredSpy).toHaveBeenCalledTimes(0);
-    expect(ifPrometheusConfigured).toHaveBeenCalledTimes(0);
+  describe('Test Permissions', () => {
+    const testCases: [string[], string[]][] = [
+      [
+        ['hosts'],
+        [
+          '.tc_submenuitem_hosts',
+          '.tc_submenuitem_cluster_inventory',
+          '.tc_submenuitem_cluster_services'
+        ]
+      ],
+      [['monitor'], ['.tc_submenuitem_cluster_monitor']],
+      [['osd'], ['.tc_submenuitem_osds', '.tc_submenuitem_crush']],
+      [['configOpt'], ['.tc_submenuitem_configuration', '.tc_submenuitem_modules']],
+      [['log'], ['.tc_submenuitem_log']],
+      [['prometheus'], ['.tc_submenuitem_monitoring']],
+      [['pool'], ['.tc_menuitem_pool']],
+      [['rbdImage'], ['.tc_submenuitem_block_images']],
+      [['rbdMirroring'], ['.tc_submenuitem_block_mirroring']],
+      [['iscsi'], ['.tc_submenuitem_block_iscsi']],
+      [['rbdImage', 'rbdMirroring', 'iscsi'], ['.tc_menuitem_block']],
+      [['nfs'], ['.tc_menuitem_nfs']],
+      [['cephfs'], ['.tc_menuitem_cephfs']],
+      [
+        ['rgw'],
+        [
+          '.tc_menuitem_rgw',
+          '.tc_submenuitem_rgw_daemons',
+          '.tc_submenuitem_rgw_buckets',
+          '.tc_submenuitem_rgw_users'
+        ]
+      ]
+    ];
+
+    for (const [disabledPermissions, selectors] of testCases) {
+      it(`When disabled permissions: ${JSON.stringify(
+        disabledPermissions
+      )} => hidden: "${selectors}"`, () => {
+        component.permissions = everythingPermittedExcept(disabledPermissions);
+        component.enabledFeature$ = of(everythingEnabledExcept());
+
+        fixture.detectChanges();
+        for (const selector of selectors) {
+          expect(fixture.debugElement.query(By.css(selector))).toBeFalsy();
+        }
+      });
+    }
+
+    for (const [enabledPermissions, selectors] of testCases) {
+      it(`When enabled permissions: ${JSON.stringify(
+        enabledPermissions
+      )} => visible: "${selectors}"`, () => {
+        component.permissions = onlyPermitted(enabledPermissions);
+        component.enabledFeature$ = of(everythingEnabledExcept());
+
+        fixture.detectChanges();
+        for (const selector of selectors) {
+          expect(fixture.debugElement.query(By.css(selector))).toBeTruthy();
+        }
+      });
+    }
   });
 
-  it('PrometheusService methods should have been called', () => {
-    const authStorageServiceSpy = spyOn(
-      TestBed.get(AuthStorageService),
-      'getPermissions'
-    ).and.returnValue(new Permissions({ 'config-opt': ['read'] }));
-    TestBed.overrideProvider(AuthStorageService, { useValue: authStorageServiceSpy });
-    fixture = TestBed.createComponent(NavigationComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
+  describe('Test FeatureToggles', () => {
+    const testCases: [Features[], string[]][] = [
+      [['rbd'], ['.tc_submenuitem_block_images']],
+      [['mirroring'], ['.tc_submenuitem_block_mirroring']],
+      [['iscsi'], ['.tc_submenuitem_block_iscsi']],
+      [['rbd', 'mirroring', 'iscsi'], ['.tc_menuitem_block']],
+      [['nfs'], ['.tc_menuitem_nfs']],
+      [['cephfs'], ['.tc_menuitem_cephfs']],
+      [
+        ['rgw'],
+        [
+          '.tc_menuitem_rgw',
+          '.tc_submenuitem_rgw_daemons',
+          '.tc_submenuitem_rgw_buckets',
+          '.tc_submenuitem_rgw_users'
+        ]
+      ]
+    ];
+
+    for (const [disabledFeatures, selectors] of testCases) {
+      it(`When disabled features: ${JSON.stringify(
+        disabledFeatures
+      )} => hidden: "${selectors}"`, () => {
+        component.enabledFeature$ = of(everythingEnabledExcept(disabledFeatures));
+        component.permissions = everythingPermittedExcept();
+
+        fixture.detectChanges();
+        for (const selector of selectors) {
+          expect(fixture.debugElement.query(By.css(selector))).toBeFalsy();
+        }
+      });
+    }
+
+    for (const [enabledFeatures, selectors] of testCases) {
+      it(`When enabled features: ${JSON.stringify(
+        enabledFeatures
+      )} => visible: "${selectors}"`, () => {
+        component.enabledFeature$ = of(onlyEnabled(enabledFeatures));
+        component.permissions = everythingPermittedExcept();
 
-    expect(ifAlertmanagerConfiguredSpy).toHaveBeenCalledTimes(1);
-    expect(ifPrometheusConfigured).toHaveBeenCalledTimes(1);
+        fixture.detectChanges();
+        for (const selector of selectors) {
+          expect(fixture.debugElement.query(By.css(selector))).toBeTruthy();
+        }
+      });
+    }
   });
 });
index b7cd7dc08c34283b43c7d33baa2a1b3aebbd1ae2..30bb8f18cf2e1d61f069bed4bf5a88ef0bd132b0 100644 (file)
@@ -1,6 +1,5 @@
 import { Component, HostBinding, OnInit } from '@angular/core';
 
-import { PrometheusService } from '../../../shared/api/prometheus.service';
 import { Icons } from '../../../shared/enum/icons.enum';
 import { Permissions } from '../../../shared/models/permissions';
 import { AuthStorageService } from '../../../shared/services/auth-storage.service';
@@ -19,13 +18,10 @@ export class NavigationComponent implements OnInit {
   @HostBinding('class.isPwdDisplayed') isPwdDisplayed = false;
 
   permissions: Permissions;
+  enabledFeature$: FeatureTogglesMap$;
   summaryData: any;
   icons = Icons;
 
-  isAlertmanagerConfigured = false;
-  isPrometheusConfigured = false;
-  enabledFeature$: FeatureTogglesMap$;
-
   isCollapsed = true;
   showMenuSidebar = true;
   displayedSubMenu = '';
@@ -36,29 +32,20 @@ export class NavigationComponent implements OnInit {
 
   constructor(
     private authStorageService: AuthStorageService,
-    private prometheusService: PrometheusService,
     private summaryService: SummaryService,
     private featureToggles: FeatureTogglesService
   ) {
     this.permissions = this.authStorageService.getPermissions();
+    this.enabledFeature$ = this.featureToggles.get();
   }
 
   ngOnInit() {
-    this.enabledFeature$ = this.featureToggles.get();
     this.summaryService.subscribe((data: any) => {
       if (!data) {
         return;
       }
       this.summaryData = data;
     });
-    if (this.permissions.configOpt.read) {
-      this.prometheusService.ifAlertmanagerConfigured(() => {
-        this.isAlertmanagerConfigured = true;
-      });
-      this.prometheusService.ifPrometheusConfigured(() => {
-        this.isPrometheusConfigured = true;
-      });
-    }
     this.authStorageService.isPwdDisplayed$.subscribe((isDisplayed) => {
       this.isPwdDisplayed = isDisplayed;
     });
index 8ead06e646c5df25a4e81a0c555b2833f583a505..d2817319d03b1c18ce91ebd5c7cec7a64da54bab 100644 (file)
@@ -1,10 +1,20 @@
 import { HttpClient } from '@angular/common/http';
-import { Injectable, NgZone } from '@angular/core';
+import { Injectable } from '@angular/core';
 
-import { Observable } from 'rxjs';
-import { shareReplay } from 'rxjs/operators';
+import { Observable, timer } from 'rxjs';
+import { observeOn, shareReplay, switchMap } from 'rxjs/operators';
 
-export type FeatureTogglesMap = Record<string, boolean>;
+import { NgZoneSchedulerService } from './ngzone-scheduler.service';
+
+export class FeatureTogglesMap {
+  rbd = true;
+  mirroring = true;
+  iscsi = true;
+  cephfs = true;
+  rgw = true;
+  nfs = true;
+}
+export type Features = keyof FeatureTogglesMap;
 export type FeatureTogglesMap$ = Observable<FeatureTogglesMap>;
 
 @Injectable({
@@ -12,20 +22,15 @@ export type FeatureTogglesMap$ = Observable<FeatureTogglesMap>;
 })
 export class FeatureTogglesService {
   readonly API_URL: string = 'api/feature_toggles';
-  readonly REFRESH_INTERVAL: number = 20000;
+  readonly REFRESH_INTERVAL: number = 30000;
   private featureToggleMap$: FeatureTogglesMap$;
 
-  constructor(private http: HttpClient, private zone: NgZone) {
-    this.featureToggleMap$ = this.http.get<FeatureTogglesMap>(this.API_URL).pipe(shareReplay(1));
-    this.zone.runOutsideAngular(() => {
-      window.setInterval(() => {
-        this.zone.run(() => {
-          this.featureToggleMap$ = this.http
-            .get<FeatureTogglesMap>(this.API_URL)
-            .pipe(shareReplay(1));
-        });
-      }, this.REFRESH_INTERVAL);
-    });
+  constructor(private http: HttpClient, protected ngZone: NgZoneSchedulerService) {
+    this.featureToggleMap$ = timer(0, this.REFRESH_INTERVAL, ngZone.leave).pipe(
+      switchMap(() => this.http.get<FeatureTogglesMap>(this.API_URL)),
+      shareReplay(1),
+      observeOn(ngZone.enter)
+    );
   }
 
   get(): FeatureTogglesMap$ {
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/ngzone-scheduler.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/ngzone-scheduler.service.ts
new file mode 100644 (file)
index 0000000..a39c646
--- /dev/null
@@ -0,0 +1,47 @@
+import { Injectable, NgZone } from '@angular/core';
+import { asyncScheduler, SchedulerLike, Subscription } from 'rxjs';
+
+abstract class NgZoneScheduler implements SchedulerLike {
+  protected scheduler = asyncScheduler;
+
+  constructor(protected zone: NgZone) {}
+
+  abstract schedule(...args: any[]): Subscription;
+
+  now(): number {
+    return this.scheduler.now();
+  }
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class LeaveNgZoneScheduler extends NgZoneScheduler {
+  constructor(zone: NgZone) {
+    super(zone);
+  }
+
+  schedule(...args: any[]): Subscription {
+    return this.zone.runOutsideAngular(() => this.scheduler.schedule.apply(this.scheduler, args));
+  }
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class EnterNgZoneScheduler extends NgZoneScheduler {
+  constructor(zone: NgZone) {
+    super(zone);
+  }
+
+  schedule(...args: any[]): Subscription {
+    return this.zone.run(() => this.scheduler.schedule.apply(this.scheduler, args));
+  }
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class NgZoneSchedulerService {
+  constructor(public leave: LeaveNgZoneScheduler, public enter: EnterNgZoneScheduler) {}
+}
index 2373df2dea33e6230efd7a8307962769e466e953..5e7c4790589663fe36525ee459ccb45e09a86a7a 100644 (file)
@@ -15,6 +15,7 @@ from ..controllers.rbd_mirroring import (
 from ..controllers.iscsi import Iscsi, IscsiTarget
 from ..controllers.cephfs import CephFS
 from ..controllers.rgw import Rgw, RgwDaemon, RgwBucket, RgwUser
+from ..controllers.nfsganesha import NFSGanesha, NFSGaneshaService, NFSGaneshaExports
 
 try:
     from typing import no_type_check, Set
@@ -28,6 +29,7 @@ class Features(Enum):
     ISCSI = 'iscsi'
     CEPHFS = 'cephfs'
     RGW = 'rgw'
+    NFS = 'nfs'
 
 
 PREDISABLED_FEATURES = set()  # type: Set[str]
@@ -40,6 +42,7 @@ Feature2Controller = {
     Features.ISCSI: [Iscsi, IscsiTarget],
     Features.CEPHFS: [CephFS],
     Features.RGW: [Rgw, RgwDaemon, RgwBucket, RgwUser],
+    Features.NFS: [NFSGanesha, NFSGaneshaService, NFSGaneshaExports],
 }
 
 
index 16b6fa5c409fef4f7f8ae1b71c2a13fe9f80cba5..e9144db406eddff2234b3bcd8adabb63690dbf71 100644 (file)
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+# pylint: disable=too-many-lines
 from __future__ import absolute_import
 
 import logging
@@ -25,7 +26,7 @@ class NFSException(DashboardException):
 class Ganesha(object):
     @classmethod
     def _get_clusters_locations(cls):
-        result = {}
+        result = {}  # type: ignore
         location_list_str = Settings.GANESHA_CLUSTERS_RADOS_POOL_NAMESPACE
         if not location_list_str:
             raise NFSException("Ganesha config location is not configured. "
@@ -83,7 +84,7 @@ class Ganesha(object):
         if not instances:
             return None
 
-        result = {}
+        result = {}  # type: ignore
         for instance in instances:
             if instance.service is None:
                 instance.service = "_default_"
@@ -755,8 +756,8 @@ class GaneshaConf(object):
         self.cluster_id = cluster_id
         self.rados_pool = rados_pool
         self.rados_namespace = rados_namespace
-        self.export_conf_blocks = []
-        self.daemons_conf_blocks = {}
+        self.export_conf_blocks = []  # type: ignore
+        self.daemons_conf_blocks = {}  # type: ignore
         self._defaults = {}
         self.exports = {}
 
@@ -900,11 +901,12 @@ class GaneshaConf(object):
 
             if len_prefix > 1:
                 # validate pseudo path
-                idx = len(parent_export.pseudo)
+                idx = len(parent_export.pseudo)  # type: ignore
                 idx = idx + 1 if idx > 1 else idx
-                real_path = "{}/{}".format(parent_export.path
-                                           if len(parent_export.path) > 1 else "",
-                                           export.pseudo[idx:])
+                real_path = "{}/{}".format(
+                    parent_export.path  # type: ignore
+                    if len(parent_export.path) > 1 else "",  # type: ignore
+                    export.pseudo[idx:])
                 if export.fsal.name == 'CEPH':
                     cfs = CephFS()
                     if export.path != real_path and not cfs.dir_exists(real_path):
@@ -923,7 +925,7 @@ class GaneshaConf(object):
         return nid
 
     def _persist_daemon_configuration(self):
-        daemon_map = {}
+        daemon_map = {}  # type: ignore
         for daemon_id in self.list_daemons():
             daemon_map[daemon_id] = []