diff --git a/package-lock.json b/package-lock.json index c0415147b0..8198f7bc79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dev": true, "requires": { "@angular-devkit/core": "0.7.4", - "rxjs": "6.2.0" + "rxjs": "^6.0.0" } }, "@angular-devkit/build-angular": { @@ -25,50 +25,50 @@ "@angular-devkit/build-webpack": "0.7.4", "@angular-devkit/core": "0.7.4", "@ngtools/webpack": "6.1.4", - "ajv": "6.4.0", - "autoprefixer": "8.6.5", - "circular-dependency-plugin": "5.0.2", - "clean-css": "4.2.1", - "copy-webpack-plugin": "4.5.2", - "file-loader": "1.1.11", - "glob": "7.1.2", - "html-webpack-plugin": "3.2.0", - "istanbul": "0.4.5", - "istanbul-instrumenter-loader": "3.0.1", - "karma-source-map-support": "1.3.0", - "less": "3.8.1", - "less-loader": "4.1.0", - "license-webpack-plugin": "1.4.0", - "loader-utils": "1.1.0", - "mini-css-extract-plugin": "0.4.1", - "minimatch": "3.0.4", - "node-sass": "4.9.3", - "opn": "5.3.0", - "parse5": "4.0.0", - "portfinder": "1.0.16", - "postcss": "6.0.23", - "postcss-import": "11.1.0", - "postcss-loader": "2.1.6", - "postcss-url": "7.3.2", - "raw-loader": "0.5.1", - "rxjs": "6.2.0", - "sass-loader": "6.0.7", - "semver": "5.5.0", - "source-map-loader": "0.2.4", - "source-map-support": "0.5.6", - "stats-webpack-plugin": "0.6.2", - "style-loader": "0.21.0", - "stylus": "0.54.5", - "stylus-loader": "3.0.2", - "tree-kill": "1.2.0", - "uglifyjs-webpack-plugin": "1.3.0", - "url-loader": "1.1.1", - "webpack": "4.9.2", - "webpack-dev-middleware": "3.1.3", - "webpack-dev-server": "3.1.5", - "webpack-merge": "4.1.4", - "webpack-sources": "1.1.0", - "webpack-subresource-integrity": "1.1.0-rc.4" + "ajv": "~6.4.0", + "autoprefixer": "^8.4.1", + "circular-dependency-plugin": "^5.0.2", + "clean-css": "^4.1.11", + "copy-webpack-plugin": "^4.5.2", + "file-loader": "^1.1.11", + "glob": "^7.0.3", + "html-webpack-plugin": "^3.0.6", + "istanbul": "^0.4.5", + "istanbul-instrumenter-loader": "^3.0.1", + "karma-source-map-support": "^1.2.0", + "less": "^3.7.1", + "less-loader": "^4.1.0", + "license-webpack-plugin": "^1.3.1", + "loader-utils": "^1.1.0", + "mini-css-extract-plugin": "~0.4.0", + "minimatch": "^3.0.4", + "node-sass": "^4.9.3", + "opn": "^5.1.0", + "parse5": "^4.0.0", + "portfinder": "^1.0.13", + "postcss": "^6.0.22", + "postcss-import": "^11.1.0", + "postcss-loader": "^2.1.5", + "postcss-url": "^7.3.2", + "raw-loader": "^0.5.1", + "rxjs": "^6.0.0", + "sass-loader": "~6.0.7", + "semver": "^5.5.0", + "source-map-loader": "^0.2.3", + "source-map-support": "^0.5.0", + "stats-webpack-plugin": "^0.6.2", + "style-loader": "^0.21.0", + "stylus": "^0.54.5", + "stylus-loader": "^3.0.2", + "tree-kill": "^1.2.0", + "uglifyjs-webpack-plugin": "^1.2.5", + "url-loader": "^1.0.1", + "webpack": "~4.9.2", + "webpack-dev-middleware": "^3.1.3", + "webpack-dev-server": "^3.1.4", + "webpack-merge": "^4.1.2", + "webpack-sources": "^1.1.0", + "webpack-subresource-integrity": "^1.1.0-rc.4" } }, "@angular-devkit/build-optimizer": { @@ -77,10 +77,10 @@ "integrity": "sha512-R+Icu9XjIaKcYFscaMBJ1DyBK2prxK3JQSFi0S//0MdNP4gBFIpCtNdOQsNXovCkpVZ7YlgmdE5+vSb39GVHHA==", "dev": true, "requires": { - "loader-utils": "1.1.0", - "source-map": "0.5.6", - "typescript": "2.9.2", - "webpack-sources": "1.1.0" + "loader-utils": "^1.1.0", + "source-map": "^0.5.6", + "typescript": "~2.9.1", + "webpack-sources": "^1.1.0" }, "dependencies": { "typescript": { @@ -99,7 +99,7 @@ "requires": { "@angular-devkit/architect": "0.7.4", "@angular-devkit/core": "0.7.4", - "rxjs": "6.2.0" + "rxjs": "^6.0.0" } }, "@angular-devkit/core": { @@ -108,10 +108,10 @@ "integrity": "sha512-Blh44vzZVzE8B9xIwjRoo7hXPGSDdlrrax0rntvt3DDGVTjsSGm43qT95aDmXiwJruOCJNC5DsaP3+tTAkAyQQ==", "dev": true, "requires": { - "ajv": "6.4.0", - "chokidar": "2.0.3", - "rxjs": "6.2.0", - "source-map": "0.5.6" + "ajv": "~6.4.0", + "chokidar": "^2.0.3", + "rxjs": "^6.0.0", + "source-map": "^0.5.6" } }, "@angular-devkit/schematics": { @@ -142,19 +142,19 @@ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.4", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "lodash.debounce": "4.0.8", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.1.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" } }, "rxjs": { @@ -163,7 +163,7 @@ "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", "dev": true, "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "source-map": { @@ -179,7 +179,7 @@ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-6.1.1.tgz", "integrity": "sha512-6o15ZtoTWlvZgu/qTz2xj25A1ZRr+BGRHxkhQDZ4hADEIUyYi96dVQxkUttXTtmACRAhK4oXkL7xleVm5iN6ow==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/cdk": { @@ -187,7 +187,7 @@ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-6.4.0.tgz", "integrity": "sha512-JEJ7OsVxoyEgsWG5c48mXLFGOUq0I8Mijar1ktI+TcIqdoLwO1XClcoh8MbgwImp3ZISfOghHVqcjLxhp4UASA==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.7.1" } }, "@angular/cli": { @@ -243,19 +243,19 @@ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.4", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "lodash.debounce": "4.0.8", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.1.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" } }, "json-schema-traverse": { @@ -270,7 +270,7 @@ "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", "dev": true, "requires": { - "is-wsl": "1.1.0" + "is-wsl": "^1.1.0" } }, "rxjs": { @@ -279,7 +279,7 @@ "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", "dev": true, "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "semver": { @@ -300,7 +300,7 @@ "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } } } @@ -310,7 +310,7 @@ "resolved": "https://registry.npmjs.org/@angular/common/-/common-6.1.1.tgz", "integrity": "sha512-mrMG0Q+BUPuiez3RKWkrMCv3r/9iJl1DoTLhLNsgWvpj0IRGcARUyJgmTZqVVVCeacjFQEM+DopbVQ7AjQCkoA==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/compiler": { @@ -318,7 +318,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-6.1.1.tgz", "integrity": "sha512-60qSglzK8lncRI13axHaJryjGvdnue5yI8yXiJEEXMHba+AJ9xfoXH2aPPqBHvUX7bU4p4fsSVGDOe7kryo/ow==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/compiler-cli": { @@ -327,10 +327,10 @@ "integrity": "sha512-J1FJbeN95Oe3hLNZnNFQUpKFxh5mb11EPKHhGScqajK1+2eZrmKfw6SRi2n4R1FPODerML+q4+uJjywjV5QSOw==", "dev": true, "requires": { - "chokidar": "1.7.0", - "minimist": "1.2.0", - "reflect-metadata": "0.1.12", - "tsickle": "0.32.1" + "chokidar": "^1.4.2", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "tsickle": "^0.32.1" }, "dependencies": { "anymatch": { @@ -339,8 +339,8 @@ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" } }, "arr-diff": { @@ -349,7 +349,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "^1.0.1" } }, "array-unique": { @@ -364,9 +364,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "chokidar": { @@ -375,15 +375,15 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.2.4", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" } }, "expand-brackets": { @@ -392,7 +392,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" } }, "extglob": { @@ -401,7 +401,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "glob-parent": { @@ -410,7 +410,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } }, "is-extglob": { @@ -425,7 +425,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "kind-of": { @@ -434,7 +434,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "micromatch": { @@ -443,19 +443,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" } }, "minimist": { @@ -476,11 +476,11 @@ "integrity": "sha512-JW9j+W0SaMSZGejIFZBk0AiPfnhljK3oLx5SaqxrJhjlvzFyPml5zqG1/PuScUj6yTe1muEqwk5CnDK0cOZmKw==", "dev": true, "requires": { - "jasmine-diff": "0.1.3", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "source-map": "0.6.1", - "source-map-support": "0.5.6" + "jasmine-diff": "^0.1.3", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map": "^0.6.0", + "source-map-support": "^0.5.0" } } } @@ -490,7 +490,7 @@ "resolved": "https://registry.npmjs.org/@angular/core/-/core-6.1.1.tgz", "integrity": "sha512-4h/8abB4N5meQHg69IV1wtNKUKe8e0w9z9s/0ZYbvFPVqWB9OkcSihsS2xmfSD3glIgSgS5424/jmiTB9G0Tcw==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/flex-layout": { @@ -498,7 +498,7 @@ "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-6.0.0-beta.18.tgz", "integrity": "sha512-1Alv3YSIZYp0CTUIESIaSQLoSVyLzuNKPa5bGM/RzOmeSrndm5plVgI9wopGfJUDiwM18R97rq/4XjDvNT/+ig==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.7.1" } }, "@angular/forms": { @@ -506,7 +506,7 @@ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-6.1.1.tgz", "integrity": "sha512-NiEMJN0INoK6khjS+YJAqt3FS2nXy3JH4J10m55e2gwzldHrsU94bWUDEOEMbPfm7dFC8G1114p/MneleoXTvg==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/http": { @@ -514,7 +514,7 @@ "resolved": "https://registry.npmjs.org/@angular/http/-/http-6.1.1.tgz", "integrity": "sha512-1VtFTSJeo1Q3pgbQ65NyMZFV3f+Jd8i4XMbmqOf+L7StosI1HE8eiDbm1SgQOuXZv0MFwgKMEXy7lzfnyl9Udw==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/language-service": { @@ -528,7 +528,7 @@ "resolved": "https://registry.npmjs.org/@angular/material/-/material-6.2.0.tgz", "integrity": "sha512-4vC2Ycrf1ORP6iGIy9qExVpbjqHJ/ObEQd72pVDQyK127O8cxhGhEiX8QvxdeAGREVxqwfhUGEK/vjH3o110fQ==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.7.1" } }, "@angular/material-moment-adapter": { @@ -536,7 +536,7 @@ "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-6.4.7.tgz", "integrity": "sha512-OGdDtpu/yRioOQXhJFCNuiOF2OgiL9VUj8ewFPi1lDtFGUFfVwU2h3hWkKLn+yuPW+DBVYla11tCNsn5dLElmA==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.7.1" } }, "@angular/platform-browser": { @@ -544,7 +544,7 @@ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-6.1.1.tgz", "integrity": "sha512-YgFP6NQgk7ZkKKfywmLC3wBZuepYLttjIvzWhbvutJpRahAw1qDQaeCXdv75DU4U8fqHDKkllZS/kIdkc3cxQw==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/platform-browser-dynamic": { @@ -552,7 +552,7 @@ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-6.1.1.tgz", "integrity": "sha512-OYXMgVapk6XmRwWgW05fN30dj1fSSiJjCXMzxxG/y+hIMe/O9HLfShADQHee9XRQJhZEdDB0rr7tOFYmH1c5Uw==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@angular/platform-server": { @@ -560,9 +560,9 @@ "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-6.1.1.tgz", "integrity": "sha512-fss9CRIAK599lb7X5aOcKdGXZ3qr5t/QfkMEYfIc7A/nJ7wupa5L2pGFvifxClJIkFMB7Q7GMQn57WgnPaU5zw==", "requires": { - "domino": "2.0.2", - "tslib": "1.9.2", - "xhr2": "0.1.4" + "domino": "^2.0.1", + "tslib": "^1.9.0", + "xhr2": "^0.1.4" } }, "@angular/router": { @@ -570,7 +570,7 @@ "resolved": "https://registry.npmjs.org/@angular/router/-/router-6.1.1.tgz", "integrity": "sha512-pYvB0wQI7/TS/BLeEy707t1wMujvM8fAlSw+BJs4iqYJwYuG9nGG3IzKvR90fZDVdseNFNa72WokXaK1BPSs8Q==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "@mrmlnc/readdir-enhanced": { @@ -579,8 +579,8 @@ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { - "call-me-maybe": "1.0.1", - "glob-to-regexp": "0.3.0" + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" } }, "@ngrx/effects": { @@ -610,9 +610,9 @@ "dev": true, "requires": { "@angular-devkit/core": "0.7.4", - "rxjs": "6.2.0", - "tree-kill": "1.2.0", - "webpack-sources": "1.1.0" + "rxjs": "^6.0.0", + "tree-kill": "^1.0.0", + "webpack-sources": "^1.1.0" } }, "@nodelib/fs.stat": { @@ -629,7 +629,7 @@ "requires": { "@angular-devkit/core": "0.8.8", "@angular-devkit/schematics": "0.8.8", - "typescript": "2.9.2" + "typescript": ">=2.6.2 <2.10" }, "dependencies": { "@angular-devkit/core": { @@ -650,19 +650,19 @@ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.4", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "lodash.debounce": "4.0.8", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.1.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" } }, "rxjs": { @@ -671,7 +671,7 @@ "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", "dev": true, "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "source-map": { @@ -714,19 +714,19 @@ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.4", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "lodash.debounce": "4.0.8", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.1.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" } }, "rxjs": { @@ -735,7 +735,7 @@ "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", "dev": true, "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "semver": { @@ -757,17 +757,17 @@ "resolved": "https://registry.npmjs.org/@swimlane/ngx-charts/-/ngx-charts-9.0.0.tgz", "integrity": "sha512-XmiEclr09p5EiZyXPqPyGD//Ai4GUpJbMYw90A24UJdFwvh8BQDDeZ1QUNIuTWkpN5XMZ8TzQ4P4qjaTypsZPw==", "requires": { - "d3-array": "1.2.4", - "d3-brush": "1.0.6", - "d3-color": "1.2.3", - "d3-force": "1.1.2", - "d3-format": "1.3.2", - "d3-hierarchy": "1.1.8", - "d3-interpolate": "1.3.2", - "d3-scale": "1.0.7", - "d3-selection": "1.3.2", - "d3-shape": "1.2.2", - "d3-time-format": "2.1.3" + "d3-array": "^1.2.1", + "d3-brush": "^1.0.4", + "d3-color": "^1.0.3", + "d3-force": "^1.1.0", + "d3-format": "^1.2.0", + "d3-hierarchy": "^1.1.5", + "d3-interpolate": "^1.1.5", + "d3-scale": "^1.0.6", + "d3-selection": "^1.1.0", + "d3-shape": "^1.2.0", + "d3-time-format": "^2.1.0" } }, "@tweenjs/tween.js": { @@ -798,7 +798,7 @@ "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", "dev": true, "requires": { - "@types/node": "6.0.111" + "@types/node": "*" } }, "@types/jasmine": { @@ -813,7 +813,7 @@ "integrity": "sha512-hYDVmQZT5VA2kigd4H4bv7vl/OhlympwREUemqBdOqtrYTo5Ytm12a5W5/nGgGYdanGVxj0x/VhZ7J3hOg/YKg==", "dev": true, "requires": { - "@types/jasmine": "2.8.7" + "@types/jasmine": "*" } }, "@types/karma": { @@ -822,8 +822,8 @@ "integrity": "sha512-26J5wva11NjLWWitm4JMRc51NtTnSf912tPonmujsPcISitGXz1KcfwQk6SRcyM1ikb09zq3aGwVcj7HYkmW6A==", "dev": true, "requires": { - "@types/bluebird": "3.5.20", - "@types/node": "6.0.111" + "@types/bluebird": "*", + "@types/node": "*" } }, "@types/node": { @@ -844,10 +844,10 @@ "integrity": "sha512-/KXM5oev+nNCLIgBjkwbk8VqxmzI56woD4VUxn95O+YeQ8hJzcSmIZ1IN3WexiqBb6srzDo2bdMbsXxgXNkz5Q==", "dev": true, "requires": { - "@types/caseless": "0.12.1", - "@types/form-data": "2.2.1", - "@types/node": "6.0.111", - "@types/tough-cookie": "2.3.3" + "@types/caseless": "*", + "@types/form-data": "*", + "@types/node": "*", + "@types/tough-cookie": "*" } }, "@types/selenium-webdriver": { @@ -875,7 +875,7 @@ "requires": { "@webassemblyjs/helper-wasm-bytecode": "1.4.3", "@webassemblyjs/wast-parser": "1.4.3", - "debug": "3.1.0", + "debug": "^3.1.0", "webassemblyjs": "1.4.3" }, "dependencies": { @@ -902,7 +902,7 @@ "integrity": "sha512-e8+KZHh+RV8MUvoSRtuT1sFXskFnWG9vbDy47Oa166xX+l0dD5sERJ21g5/tcH8Yo95e9IN3u7Jc3NbhnUcSkw==", "dev": true, "requires": { - "debug": "3.1.0" + "debug": "^3.1.0" }, "dependencies": { "debug": { @@ -947,7 +947,7 @@ "@webassemblyjs/helper-buffer": "1.4.3", "@webassemblyjs/helper-wasm-bytecode": "1.4.3", "@webassemblyjs/wasm-gen": "1.4.3", - "debug": "3.1.0" + "debug": "^3.1.0" }, "dependencies": { "debug": { @@ -967,7 +967,7 @@ "integrity": "sha512-4u0LJLSPzuRDWHwdqsrThYn+WqMFVqbI2ltNrHvZZkzFPO8XOZ0HFQ5eVc4jY/TNHgXcnwrHjONhPGYuuf//KQ==", "dev": true, "requires": { - "leb": "0.3.0" + "leb": "^0.3.0" } }, "@webassemblyjs/validation": { @@ -993,7 +993,7 @@ "@webassemblyjs/wasm-opt": "1.4.3", "@webassemblyjs/wasm-parser": "1.4.3", "@webassemblyjs/wast-printer": "1.4.3", - "debug": "3.1.0" + "debug": "^3.1.0" }, "dependencies": { "debug": { @@ -1028,7 +1028,7 @@ "@webassemblyjs/helper-buffer": "1.4.3", "@webassemblyjs/wasm-gen": "1.4.3", "@webassemblyjs/wasm-parser": "1.4.3", - "debug": "3.1.0" + "debug": "^3.1.0" }, "dependencies": { "debug": { @@ -1065,7 +1065,7 @@ "@webassemblyjs/floating-point-hex-parser": "1.4.3", "@webassemblyjs/helper-code-frame": "1.4.3", "@webassemblyjs/helper-fsm": "1.4.3", - "long": "3.2.0", + "long": "^3.2.0", "webassemblyjs": "1.4.3" } }, @@ -1077,7 +1077,7 @@ "requires": { "@webassemblyjs/ast": "1.4.3", "@webassemblyjs/wast-parser": "1.4.3", - "long": "3.2.0" + "long": "^3.2.0" } }, "@webpack-contrib/schema-utils": { @@ -1086,12 +1086,12 @@ "integrity": "sha512-LonryJP+FxQQHsjGBi6W786TQB1Oym+agTpY0c+Kj8alnIw+DLUJb6SI8Y1GHGhLCH1yPRrucjObUmxNICQ1pg==", "dev": true, "requires": { - "ajv": "6.4.0", - "ajv-keywords": "3.2.0", - "chalk": "2.4.1", - "strip-ansi": "4.0.0", - "text-table": "0.2.0", - "webpack-log": "1.2.0" + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chalk": "^2.3.2", + "strip-ansi": "^4.0.0", + "text-table": "^0.2.0", + "webpack-log": "^1.1.2" }, "dependencies": { "ansi-regex": { @@ -1106,9 +1106,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "strip-ansi": { @@ -1117,7 +1117,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -1134,7 +1134,7 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.18", "negotiator": "0.6.1" } }, @@ -1150,7 +1150,7 @@ "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", "dev": true, "requires": { - "acorn": "5.5.3" + "acorn": "^5.0.0" } }, "acorn-jsx": { @@ -1159,7 +1159,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -1188,7 +1188,7 @@ "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", "dev": true, "requires": { - "es6-promisify": "5.0.0" + "es6-promisify": "^5.0.0" } }, "ajv": { @@ -1197,10 +1197,10 @@ "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=", "dev": true, "requires": { - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1", - "uri-js": "3.0.2" + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0", + "uri-js": "^3.0.2" } }, "ajv-errors": { @@ -1221,9 +1221,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" }, "dependencies": { "kind-of": { @@ -1232,7 +1232,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -1248,7 +1248,7 @@ "resolved": "https://registry.npmjs.org/angular2-virtual-scroll/-/angular2-virtual-scroll-0.3.2.tgz", "integrity": "sha512-eyPb6FnaA8d4lBh3v31F3YLLblr9Nn8zv25uKVmxPkA2/te6QDg0sPMqy6o8GouwW+U9LKzcUJZZBHa0ICY/rg==", "requires": { - "@tweenjs/tween.js": "17.2.0" + "@tweenjs/tween.js": "^17.1.0" } }, "ansi-colors": { @@ -1257,7 +1257,7 @@ "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "ansi-wrap": "0.1.0" + "ansi-wrap": "^0.1.0" } }, "ansi-cyan": { @@ -1311,7 +1311,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "ansi-wrap": { @@ -1326,8 +1326,8 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "3.1.10", - "normalize-path": "2.1.1" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, "app-root-path": { @@ -1342,7 +1342,7 @@ "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", "dev": true, "requires": { - "buffer-equal": "1.0.0" + "buffer-equal": "^1.0.0" } }, "append-transform": { @@ -1351,7 +1351,7 @@ "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", "dev": true, "requires": { - "default-require-extensions": "2.0.0" + "default-require-extensions": "^2.0.0" } }, "aproba": { @@ -1372,8 +1372,8 @@ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "argparse": { @@ -1381,7 +1381,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "argv": { @@ -1402,7 +1402,7 @@ "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", "dev": true, "requires": { - "make-iterator": "1.0.1" + "make-iterator": "^1.0.0" } }, "arr-flatten": { @@ -1417,7 +1417,7 @@ "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", "dev": true, "requires": { - "make-iterator": "1.0.1" + "make-iterator": "^1.0.0" } }, "arr-union": { @@ -1450,8 +1450,8 @@ "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", "dev": true, "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.12.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" } }, "array-initial": { @@ -1460,8 +1460,8 @@ "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", "dev": true, "requires": { - "array-slice": "1.1.0", - "is-number": "4.0.0" + "array-slice": "^1.0.0", + "is-number": "^4.0.0" }, "dependencies": { "is-number": { @@ -1478,7 +1478,7 @@ "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, "requires": { - "is-number": "4.0.0" + "is-number": "^4.0.0" }, "dependencies": { "is-number": { @@ -1501,9 +1501,9 @@ "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, "requires": { - "default-compare": "1.0.0", - "get-value": "2.0.6", - "kind-of": "5.1.0" + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" }, "dependencies": { "kind-of": { @@ -1520,7 +1520,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -1566,9 +1566,9 @@ "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "assert": { @@ -1610,10 +1610,10 @@ "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0", - "process-nextick-args": "1.0.7", - "stream-exhaust": "1.0.2" + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^1.0.7", + "stream-exhaust": "^1.0.1" }, "dependencies": { "process-nextick-args": { @@ -1649,7 +1649,7 @@ "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", "dev": true, "requires": { - "async-done": "1.3.1" + "async-done": "^1.2.2" } }, "asynckit": { @@ -1670,12 +1670,12 @@ "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", "dev": true, "requires": { - "browserslist": "3.2.8", - "caniuse-lite": "1.0.30000877", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "6.0.23", - "postcss-value-parser": "3.3.0" + "browserslist": "^3.2.8", + "caniuse-lite": "^1.0.30000864", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.23", + "postcss-value-parser": "^3.2.3" } }, "aws-sign2": { @@ -1696,9 +1696,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" }, "dependencies": { "ansi-styles": { @@ -1713,11 +1713,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "supports-color": { @@ -1734,14 +1734,14 @@ "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.10", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" }, "dependencies": { "source-map": { @@ -1758,7 +1758,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "6.26.0" + "babel-runtime": "^6.22.0" } }, "babel-runtime": { @@ -1767,8 +1767,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.7", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-template": { @@ -1777,11 +1777,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.10" + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" } }, "babel-traverse": { @@ -1790,15 +1790,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.4", - "lodash": "4.17.10" + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" } }, "babel-types": { @@ -1807,10 +1807,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.10", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -1825,15 +1825,15 @@ "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", "dev": true, "requires": { - "arr-filter": "1.1.2", - "arr-flatten": "1.1.0", - "arr-map": "2.0.2", - "array-each": "1.0.1", - "array-initial": "1.1.0", - "array-last": "1.3.0", - "async-done": "1.3.1", - "async-settle": "1.0.0", - "now-and-later": "2.0.0" + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" } }, "backo2": { @@ -1854,13 +1854,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" }, "dependencies": { "define-property": { @@ -1869,7 +1869,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -1878,7 +1878,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -1887,7 +1887,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -1896,9 +1896,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -1934,7 +1934,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "better-assert": { @@ -1971,7 +1971,7 @@ "dev": true, "optional": true, "requires": { - "inherits": "2.0.3" + "inherits": "~2.0.0" } }, "blocking-proxy": { @@ -1980,7 +1980,7 @@ "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.2.0" }, "dependencies": { "minimist": { @@ -2010,15 +2010,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.3", + "depd": "~1.1.1", + "http-errors": "~1.6.2", "iconv-lite": "0.4.19", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.16" + "type-is": "~1.6.15" }, "dependencies": { "qs": { @@ -2035,12 +2035,12 @@ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", "dev": true, "requires": { - "array-flatten": "2.1.1", - "deep-equal": "1.0.1", - "dns-equal": "1.0.0", - "dns-txt": "2.0.2", - "multicast-dns": "6.2.3", - "multicast-dns-service-types": "1.1.0" + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" } }, "boolbase": { @@ -2055,7 +2055,7 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -2065,16 +2065,16 @@ "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.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" + "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" }, "dependencies": { "extend-shallow": { @@ -2083,7 +2083,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -2100,12 +2100,12 @@ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "browserify-cipher": { @@ -2114,9 +2114,9 @@ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "dev": true, "requires": { - "browserify-aes": "1.2.0", - "browserify-des": "1.0.2", - "evp_bytestokey": "1.0.3" + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, "browserify-des": { @@ -2125,10 +2125,10 @@ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "browserify-rsa": { @@ -2137,8 +2137,8 @@ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" } }, "browserify-sign": { @@ -2147,13 +2147,13 @@ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "elliptic": "6.4.1", - "inherits": "2.0.3", - "parse-asn1": "5.1.1" + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" } }, "browserify-zlib": { @@ -2162,7 +2162,7 @@ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, "requires": { - "pako": "1.0.6" + "pako": "~1.0.5" } }, "browserslist": { @@ -2171,8 +2171,8 @@ "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", "dev": true, "requires": { - "caniuse-lite": "1.0.30000877", - "electron-to-chromium": "1.3.58" + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" } }, "browserstack": { @@ -2181,7 +2181,7 @@ "integrity": "sha512-O8VMT64P9NOLhuIoD4YngyxBURefaSdR4QdhG8l6HZ9VxtU7jc3m6jLufFwKA5gaf7fetfB2TnRJnMxyob+heg==", "dev": true, "requires": { - "https-proxy-agent": "2.2.1" + "https-proxy-agent": "^2.2.1" } }, "browserstack-local": { @@ -2190,11 +2190,11 @@ "integrity": "sha512-ilZlmiy7XYJxsztYan7XueHVr3Ix9EVh/mCiYN1G53wRPEW/hg1KMsseM6UExzVbexEqFEfwjkBLeFlSqxh+bQ==", "dev": true, "requires": { - "https-proxy-agent": "2.2.1", - "is-running": "2.1.0", - "ps-tree": "1.1.1", - "sinon": "1.17.7", - "temp-fs": "0.9.9" + "https-proxy-agent": "^2.2.1", + "is-running": "^2.0.0", + "ps-tree": "=1.1.1", + "sinon": "^1.17.6", + "temp-fs": "^0.9.9" } }, "buffer": { @@ -2203,9 +2203,9 @@ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "base64-js": "1.3.0", - "ieee754": "1.1.12", - "isarray": "1.0.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, "buffer-alloc": { @@ -2214,8 +2214,8 @@ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "dev": true, "requires": { - "buffer-alloc-unsafe": "1.1.0", - "buffer-fill": "1.0.0" + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" } }, "buffer-alloc-unsafe": { @@ -2290,19 +2290,19 @@ "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", "dev": true, "requires": { - "bluebird": "3.5.1", - "chownr": "1.0.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "lru-cache": "4.1.3", - "mississippi": "2.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "promise-inflight": "1.0.1", - "rimraf": "2.6.2", - "ssri": "5.3.0", - "unique-filename": "1.1.0", - "y18n": "4.0.0" + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" } }, "cache-base": { @@ -2311,15 +2311,15 @@ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" } }, "call-me-maybe": { @@ -2334,7 +2334,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsite": { @@ -2355,8 +2355,8 @@ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", "dev": true, "requires": { - "no-case": "2.3.2", - "upper-case": "1.1.3" + "no-case": "^2.2.0", + "upper-case": "^1.1.1" } }, "camelcase": { @@ -2372,8 +2372,8 @@ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" }, "dependencies": { "camelcase": { @@ -2403,8 +2403,8 @@ "dev": true, "optional": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "chalk": { @@ -2413,9 +2413,9 @@ "integrity": "sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" }, "dependencies": { "has-flag": { @@ -2430,7 +2430,7 @@ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } } } @@ -2441,18 +2441,18 @@ "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", "dev": true, "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.4", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.1.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.1.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.0" } }, "chownr": { @@ -2473,8 +2473,8 @@ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "circular-dependency-plugin": { @@ -2494,10 +2494,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { "define-property": { @@ -2506,7 +2506,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } @@ -2517,7 +2517,7 @@ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", "dev": true, "requires": { - "source-map": "0.6.1" + "source-map": "~0.6.0" }, "dependencies": { "source-map": { @@ -2534,7 +2534,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "cli-width": { @@ -2550,8 +2550,8 @@ "dev": true, "optional": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" }, "dependencies": { @@ -2582,10 +2582,10 @@ "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", "dev": true, "requires": { - "for-own": "1.0.0", - "is-plain-object": "2.0.4", - "kind-of": "6.0.2", - "shallow-clone": "1.0.0" + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" } }, "clone-stats": { @@ -2600,9 +2600,9 @@ "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { - "inherits": "2.0.3", - "process-nextick-args": "2.0.0", - "readable-stream": "2.3.6" + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" } }, "co": { @@ -2624,7 +2624,7 @@ "dev": true, "requires": { "argv": "0.0.2", - "request": "2.87.0", + "request": "^2.81.0", "urlgrey": "0.4.4" } }, @@ -2634,12 +2634,12 @@ "integrity": "sha512-JgFMudx0n50IuE/ydAfnkksCwQkWSVWgYvhDPHZgDUbmsiYC22VuEXKu5l8Hhx9UJsLgjWDLjTAFGj2WaW5DUA==", "dev": true, "requires": { - "app-root-path": "2.1.0", - "css-selector-tokenizer": "0.7.0", - "cssauron": "1.4.0", - "semver-dsl": "1.0.1", - "source-map": "0.5.7", - "sprintf-js": "1.1.1" + "app-root-path": "^2.1.0", + "css-selector-tokenizer": "^0.7.0", + "cssauron": "^1.4.0", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.1" }, "dependencies": { "source-map": { @@ -2662,9 +2662,9 @@ "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", "dev": true, "requires": { - "arr-map": "2.0.2", - "for-own": "1.0.0", - "make-iterator": "1.0.1" + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" } }, "collection-visit": { @@ -2673,8 +2673,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, "color-convert": { @@ -2683,7 +2683,7 @@ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.1.1" } }, "color-name": { @@ -2710,7 +2710,7 @@ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "4.17.10" + "lodash": "^4.5.0" } }, "combined-stream": { @@ -2719,7 +2719,7 @@ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "commander": { @@ -2764,7 +2764,7 @@ "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", "dev": true, "requires": { - "mime-db": "1.35.0" + "mime-db": ">= 1.34.0 < 2" }, "dependencies": { "mime-db": { @@ -2781,13 +2781,13 @@ "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.5", "bytes": "3.0.0", - "compressible": "2.0.14", + "compressible": "~2.0.14", "debug": "2.6.9", - "on-headers": "1.0.1", + "on-headers": "~1.0.1", "safe-buffer": "5.1.2", - "vary": "1.1.2" + "vary": "~1.1.2" } }, "concat-map": { @@ -2802,10 +2802,10 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "1.1.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "connect": { @@ -2816,7 +2816,7 @@ "requires": { "debug": "2.6.9", "finalhandler": "1.1.0", - "parseurl": "1.3.2", + "parseurl": "~1.3.2", "utils-merge": "1.0.1" }, "dependencies": { @@ -2827,12 +2827,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" } }, "statuses": { @@ -2861,7 +2861,7 @@ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { - "date-now": "0.1.4" + "date-now": "^0.1.4" } }, "console-control-strings": { @@ -2912,12 +2912,12 @@ "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", "dev": true, "requires": { - "aproba": "1.2.0", - "fs-write-stream-atomic": "1.0.10", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" } }, "copy-descriptor": { @@ -2932,8 +2932,8 @@ "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", "dev": true, "requires": { - "each-props": "1.3.2", - "is-plain-object": "2.0.4" + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" } }, "copy-webpack-plugin": { @@ -2942,14 +2942,14 @@ "integrity": "sha512-zmC33E8FFSq3AbflTvqvPvBo621H36Afsxlui91d+QyZxPIuXghfnTsa1CuqiAaCPgJoSUWfTFbKJnadZpKEbQ==", "dev": true, "requires": { - "cacache": "10.0.4", - "find-cache-dir": "1.0.0", - "globby": "7.1.1", - "is-glob": "4.0.0", - "loader-utils": "1.1.0", - "minimatch": "3.0.4", - "p-limit": "1.2.0", - "serialize-javascript": "1.5.0" + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" }, "dependencies": { "globby": { @@ -2958,12 +2958,12 @@ "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", "dev": true, "requires": { - "array-union": "1.0.2", - "dir-glob": "2.0.0", - "glob": "7.1.2", - "ignore": "3.3.8", - "pify": "3.0.0", - "slash": "1.0.0" + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" } } } @@ -2985,10 +2985,10 @@ "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", "dev": true, "requires": { - "is-directory": "0.3.1", - "js-yaml": "3.11.0", - "parse-json": "4.0.0", - "require-from-string": "2.0.2" + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" }, "dependencies": { "parse-json": { @@ -2997,8 +2997,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "1.3.1", - "json-parse-better-errors": "1.0.2" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } } } @@ -3009,8 +3009,8 @@ "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "dev": true, "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.1" + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" } }, "create-hash": { @@ -3019,11 +3019,11 @@ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "md5.js": "1.3.4", - "ripemd160": "2.0.2", - "sha.js": "2.4.11" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, "create-hmac": { @@ -3032,12 +3032,12 @@ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "inherits": "2.0.3", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "cross-spawn": { @@ -3047,8 +3047,8 @@ "dev": true, "optional": true, "requires": { - "lru-cache": "4.1.3", - "which": "1.3.1" + "lru-cache": "^4.0.1", + "which": "^1.2.9" } }, "crypto-browserify": { @@ -3057,17 +3057,17 @@ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "requires": { - "browserify-cipher": "1.0.1", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.3", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "diffie-hellman": "5.0.3", - "inherits": "2.0.3", - "pbkdf2": "3.0.16", - "public-encrypt": "4.0.2", - "randombytes": "2.0.6", - "randomfill": "1.0.4" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" } }, "css-parse": { @@ -3082,10 +3082,10 @@ "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dev": true, "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", + "boolbase": "~1.0.0", + "css-what": "2.1", "domutils": "1.5.1", - "nth-check": "1.0.1" + "nth-check": "~1.0.1" } }, "css-selector-tokenizer": { @@ -3094,9 +3094,9 @@ "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", "dev": true, "requires": { - "cssesc": "0.1.0", - "fastparse": "1.1.1", - "regexpu-core": "1.0.0" + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" } }, "css-what": { @@ -3111,7 +3111,7 @@ "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", "dev": true, "requires": { - "through": "2.3.8" + "through": "X.X.X" } }, "cssesc": { @@ -3132,7 +3132,7 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "1.0.2" + "array-find-index": "^1.0.1" } }, "custom-event": { @@ -3153,7 +3153,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.44" + "es5-ext": "^0.10.9" } }, "d3-array": { @@ -3166,11 +3166,11 @@ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.6.tgz", "integrity": "sha512-lGSiF5SoSqO5/mYGD5FAeGKKS62JdA1EV7HPrU2b5rTX4qEJJtpjaGLJngjnkewQy7UnGstnFd3168wpf5z76w==", "requires": { - "d3-dispatch": "1.0.5", - "d3-drag": "1.2.3", - "d3-interpolate": "1.3.2", - "d3-selection": "1.3.2", - "d3-transition": "1.1.3" + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" } }, "d3-collection": { @@ -3193,8 +3193,8 @@ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.3.tgz", "integrity": "sha512-8S3HWCAg+ilzjJsNtWW1Mutl74Nmzhb9yU6igspilaJzeZVFktmY6oO9xOh5TDk+BM2KrNFjttZNoJJmDnkjkg==", "requires": { - "d3-dispatch": "1.0.5", - "d3-selection": "1.3.2" + "d3-dispatch": "1", + "d3-selection": "1" } }, "d3-ease": { @@ -3207,10 +3207,10 @@ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.2.tgz", "integrity": "sha512-p1vcHAUF1qH7yR+e8ip7Bs61AHjLeKkIn8Z2gzwU2lwEf2wkSpWdjXG0axudTHsVFnYGlMkFaEsVy2l8tAg1Gw==", "requires": { - "d3-collection": "1.0.7", - "d3-dispatch": "1.0.5", - "d3-quadtree": "1.0.5", - "d3-timer": "1.0.9" + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" } }, "d3-format": { @@ -3228,7 +3228,7 @@ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.3.2.tgz", "integrity": "sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==", "requires": { - "d3-color": "1.2.3" + "d3-color": "1" } }, "d3-path": { @@ -3246,13 +3246,13 @@ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", "requires": { - "d3-array": "1.2.4", - "d3-collection": "1.0.7", - "d3-color": "1.2.3", - "d3-format": "1.3.2", - "d3-interpolate": "1.3.2", - "d3-time": "1.0.10", - "d3-time-format": "2.1.3" + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-color": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" } }, "d3-selection": { @@ -3265,7 +3265,7 @@ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.2.tgz", "integrity": "sha512-hUGEozlKecFZ2bOSNt7ENex+4Tk9uc/m0TtTEHBvitCBxUNjhzm5hS2GrrVRD/ae4IylSmxGeqX5tWC2rASMlQ==", "requires": { - "d3-path": "1.0.7" + "d3-path": "1" } }, "d3-time": { @@ -3278,7 +3278,7 @@ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.3.tgz", "integrity": "sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==", "requires": { - "d3-time": "1.0.10" + "d3-time": "1" } }, "d3-timer": { @@ -3291,12 +3291,12 @@ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.3.tgz", "integrity": "sha512-tEvo3qOXL6pZ1EzcXxFcPNxC/Ygivu5NoBY6mbzidATAeML86da+JfVIUzon3dNM6UX6zjDx+xbYDmMVtTSjuA==", "requires": { - "d3-color": "1.2.3", - "d3-dispatch": "1.0.5", - "d3-ease": "1.0.5", - "d3-interpolate": "1.3.2", - "d3-selection": "1.3.2", - "d3-timer": "1.0.9" + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" } }, "dashdash": { @@ -3305,7 +3305,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "date-format": { @@ -3365,7 +3365,7 @@ "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, "requires": { - "kind-of": "5.1.0" + "kind-of": "^5.0.2" }, "dependencies": { "kind-of": { @@ -3382,7 +3382,7 @@ "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", "dev": true, "requires": { - "strip-bom": "3.0.0" + "strip-bom": "^3.0.0" }, "dependencies": { "strip-bom": { @@ -3405,8 +3405,8 @@ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", "dev": true, "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" + "foreach": "^2.0.5", + "object-keys": "^1.0.8" } }, "define-property": { @@ -3415,8 +3415,8 @@ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -3425,7 +3425,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -3434,7 +3434,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -3443,9 +3443,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -3456,12 +3456,12 @@ "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", "dev": true, "requires": { - "globby": "6.1.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "p-map": "1.2.0", - "pify": "3.0.0", - "rimraf": "2.6.2" + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" }, "dependencies": { "globby": { @@ -3470,11 +3470,11 @@ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "dependencies": { "pify": { @@ -3505,12 +3505,12 @@ "integrity": "sha1-fP7PXvffuAL60nq49b5a5UbFt54=", "dev": true, "requires": { - "async": "1.5.2", - "bluebird": "3.5.1", - "extend-shallow": "2.0.1", - "lazy-cache": "1.0.4", - "matched": "0.4.4", - "rimraf": "2.6.2" + "async": "^1.5.2", + "bluebird": "^3.3.5", + "extend-shallow": "^2.0.1", + "lazy-cache": "^1.0.4", + "matched": "^0.4.1", + "rimraf": "^2.5.2" }, "dependencies": { "extend-shallow": { @@ -3519,7 +3519,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -3536,8 +3536,8 @@ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "destroy": { @@ -3558,7 +3558,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "detect-node": { @@ -3585,9 +3585,9 @@ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, "dir-glob": { @@ -3596,8 +3596,8 @@ "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", "dev": true, "requires": { - "arrify": "1.0.1", - "path-type": "3.0.0" + "arrify": "^1.0.1", + "path-type": "^3.0.0" } }, "dns-equal": { @@ -3612,8 +3612,8 @@ "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", "dev": true, "requires": { - "ip": "1.1.5", - "safe-buffer": "5.1.2" + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" } }, "dns-txt": { @@ -3622,7 +3622,7 @@ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", "dev": true, "requires": { - "buffer-indexof": "1.1.1" + "buffer-indexof": "^1.0.0" } }, "doctrine": { @@ -3631,8 +3631,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "dom-converter": { @@ -3641,7 +3641,7 @@ "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", "dev": true, "requires": { - "utila": "0.3.3" + "utila": "~0.3" }, "dependencies": { "utila": { @@ -3658,10 +3658,10 @@ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "1.0.1", - "ent": "2.2.0", - "extend": "3.0.1", - "void-elements": "2.0.1" + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" } }, "dom-serializer": { @@ -3670,8 +3670,8 @@ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", "dev": true, "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" + "domelementtype": "~1.1.1", + "entities": "~1.1.1" }, "dependencies": { "domelementtype": { @@ -3700,7 +3700,7 @@ "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", "dev": true, "requires": { - "domelementtype": "1.3.0" + "domelementtype": "1" } }, "domino": { @@ -3714,13 +3714,13 @@ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "dev": true, "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" + "dom-serializer": "0", + "domelementtype": "1" } }, "duplexer": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -3730,10 +3730,10 @@ "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, "each-props": { @@ -3742,8 +3742,8 @@ "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", "dev": true, "requires": { - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0" + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" } }, "ecc-jsbn": { @@ -3753,7 +3753,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "ee-first": { @@ -3780,13 +3780,13 @@ "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.5", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, "emojis-list": { @@ -3807,7 +3807,7 @@ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.4.0" } }, "engine.io": { @@ -3816,12 +3816,12 @@ "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.4", "base64id": "1.0.0", "cookie": "0.3.1", - "debug": "3.1.0", - "engine.io-parser": "2.1.2", - "ws": "3.3.3" + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" }, "dependencies": { "debug": { @@ -3843,14 +3843,14 @@ "requires": { "component-emitter": "1.2.1", "component-inherit": "0.0.3", - "debug": "3.1.0", - "engine.io-parser": "2.1.2", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", "has-cors": "1.1.0", "indexof": "0.0.1", "parseqs": "0.0.5", "parseuri": "0.0.5", - "ws": "3.3.3", - "xmlhttprequest-ssl": "1.5.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" }, "dependencies": { @@ -3872,10 +3872,10 @@ "dev": true, "requires": { "after": "0.8.2", - "arraybuffer.slice": "0.0.7", + "arraybuffer.slice": "~0.0.7", "base64-arraybuffer": "0.1.5", "blob": "0.0.4", - "has-binary2": "1.0.3" + "has-binary2": "~1.0.2" } }, "enhanced-resolve": { @@ -3884,9 +3884,9 @@ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "tapable": "1.0.0" + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" } }, "ent": { @@ -3907,7 +3907,7 @@ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { - "prr": "1.0.1" + "prr": "~1.0.1" } }, "error-ex": { @@ -3916,7 +3916,7 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "error-stack-parser": { @@ -3924,7 +3924,7 @@ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.1.tgz", "integrity": "sha1-oyArj7AxFKqbQKDjZp5IsrZaAQo=", "requires": { - "stackframe": "1.0.4" + "stackframe": "^1.0.3" } }, "es-abstract": { @@ -3933,11 +3933,11 @@ "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.1", - "has": "1.0.3", - "is-callable": "1.1.4", - "is-regex": "1.0.4" + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" } }, "es-to-primitive": { @@ -3946,9 +3946,9 @@ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", "dev": true, "requires": { - "is-callable": "1.1.4", - "is-date-object": "1.0.1", - "is-symbol": "1.0.1" + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.1" } }, "es5-ext": { @@ -3957,9 +3957,9 @@ "integrity": "sha512-TO4Vt9IhW3FzDKLDOpoA8VS9BCV4b9WTf6BqvMOgfoa8wX73F3Kh3y2J7yTstTaXlQ0k1vq4DH2vw6RSs42z+g==", "dev": true, "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "next-tick": "1.0.0" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" } }, "es6-iterator": { @@ -3968,9 +3968,9 @@ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.44", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, "es6-map": { @@ -3979,12 +3979,12 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.44", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" } }, "es6-promise": { @@ -3999,7 +3999,7 @@ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { - "es6-promise": "4.2.4" + "es6-promise": "^4.0.3" } }, "es6-set": { @@ -4008,11 +4008,11 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.44", - "es6-iterator": "2.0.3", + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" + "event-emitter": "~0.3.5" } }, "es6-symbol": { @@ -4021,8 +4021,8 @@ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.44" + "d": "1", + "es5-ext": "~0.10.14" } }, "es6-weak-map": { @@ -4031,10 +4031,10 @@ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.44", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, "escape-html": { @@ -4055,11 +4055,11 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" }, "dependencies": { "esprima": { @@ -4075,7 +4075,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -4086,10 +4086,10 @@ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", "dev": true, "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.1", - "estraverse": "4.2.0" + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" }, "dependencies": { "estraverse": { @@ -4106,39 +4106,39 @@ "integrity": "sha1-5MyPoPAJ+4KaquI4VaKTYL4fbBE=", "dev": true, "requires": { - "chalk": "1.1.3", - "concat-stream": "1.6.2", - "debug": "2.6.9", - "doctrine": "1.5.0", - "es6-map": "0.1.5", - "escope": "3.6.0", - "espree": "3.5.4", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "1.3.1", - "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.8", - "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.17.2", - "is-resolvable": "1.1.0", - "js-yaml": "3.11.0", - "json-stable-stringify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.10", - "mkdirp": "0.5.1", - "optionator": "0.8.2", - "path-is-absolute": "1.0.1", - "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", - "require-uncached": "1.0.3", - "shelljs": "0.6.1", - "strip-json-comments": "1.0.4", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "chalk": "^1.1.3", + "concat-stream": "^1.4.6", + "debug": "^2.1.1", + "doctrine": "^1.2.2", + "es6-map": "^0.1.3", + "escope": "^3.6.0", + "espree": "^3.1.6", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^1.1.1", + "glob": "^7.0.3", + "globals": "^9.2.0", + "ignore": "^3.1.2", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "optionator": "^0.8.1", + "path-is-absolute": "^1.0.0", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.6.0", + "strip-json-comments": "~1.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" }, "dependencies": { "ansi-styles": { @@ -4153,11 +4153,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "estraverse": { @@ -4180,8 +4180,8 @@ "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", "dev": true, "requires": { - "esrecurse": "4.2.1", - "estraverse": "4.2.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" }, "dependencies": { "estraverse": { @@ -4198,8 +4198,8 @@ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.5.3", - "acorn-jsx": "3.0.1" + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" } }, "esprima": { @@ -4213,7 +4213,7 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.1.0" }, "dependencies": { "estraverse": { @@ -4248,23 +4248,23 @@ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.44" + "d": "1", + "es5-ext": "~0.10.14" } }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" } }, "eventemitter3": { @@ -4285,7 +4285,7 @@ "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", "dev": true, "requires": { - "original": "1.0.2" + "original": ">=0.0.5" } }, "evp_bytestokey": { @@ -4294,8 +4294,8 @@ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.2" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, "execa": { @@ -4304,13 +4304,13 @@ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" }, "dependencies": { "cross-spawn": { @@ -4319,9 +4319,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.3", - "shebang-command": "1.2.0", - "which": "1.3.1" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } } } @@ -4344,9 +4344,9 @@ "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, "requires": { - "array-slice": "0.2.3", - "array-unique": "0.2.1", - "braces": "0.1.5" + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" }, "dependencies": { "array-slice": { @@ -4367,7 +4367,7 @@ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", "dev": true, "requires": { - "expand-range": "0.1.1" + "expand-range": "^0.1.0" } }, "expand-range": { @@ -4376,8 +4376,8 @@ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { - "is-number": "0.1.1", - "repeat-string": "0.2.2" + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" } }, "is-number": { @@ -4400,13 +4400,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -4415,7 +4415,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -4424,7 +4424,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -4435,7 +4435,7 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "2.2.4" + "fill-range": "^2.1.0" }, "dependencies": { "fill-range": { @@ -4444,11 +4444,11 @@ "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "3.0.0", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" } }, "is-number": { @@ -4457,7 +4457,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "isobject": { @@ -4475,7 +4475,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -4486,7 +4486,7 @@ "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.1" } }, "express": { @@ -4495,36 +4495,36 @@ "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.4", + "proxy-addr": "~2.0.3", "qs": "6.5.1", - "range-parser": "1.2.0", + "range-parser": "~1.2.0", "safe-buffer": "5.1.1", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.4.0", - "type-is": "1.6.16", + "statuses": "~1.4.0", + "type-is": "~1.6.16", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { "array-flatten": { @@ -4559,8 +4559,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -4569,7 +4569,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -4580,14 +4580,14 @@ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -4596,7 +4596,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { @@ -4605,7 +4605,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { @@ -4614,7 +4614,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -4623,7 +4623,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -4632,9 +4632,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -4651,9 +4651,9 @@ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" } }, "fast-deep-equal": { @@ -4668,12 +4668,12 @@ "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", "dev": true, "requires": { - "@mrmlnc/readdir-enhanced": "2.2.1", - "@nodelib/fs.stat": "1.1.2", - "glob-parent": "3.1.0", - "is-glob": "4.0.0", - "merge2": "1.2.2", - "micromatch": "3.1.10" + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.0.1", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.1", + "micromatch": "^3.1.10" } }, "fast-json-stable-stringify": { @@ -4700,7 +4700,7 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": "0.7.0" + "websocket-driver": ">=0.5.1" } }, "figures": { @@ -4709,8 +4709,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "file-entry-cache": { @@ -4719,8 +4719,8 @@ "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "file-loader": { @@ -4729,8 +4729,8 @@ "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { - "loader-utils": "1.1.0", - "schema-utils": "0.4.7" + "loader-utils": "^1.0.2", + "schema-utils": "^0.4.5" } }, "filename-regex": { @@ -4745,8 +4745,8 @@ "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", "dev": true, "requires": { - "glob": "7.1.2", - "minimatch": "3.0.4" + "glob": "^7.0.3", + "minimatch": "^3.0.3" } }, "fill-range": { @@ -4755,10 +4755,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { @@ -4767,7 +4767,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -4779,12 +4779,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" } }, "find-cache-dir": { @@ -4793,9 +4793,9 @@ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", "dev": true, "requires": { - "commondir": "1.0.1", - "make-dir": "1.3.0", - "pkg-dir": "2.0.0" + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" } }, "find-up": { @@ -4804,7 +4804,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "findup-sync": { @@ -4813,10 +4813,10 @@ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "1.0.0", - "is-glob": "3.1.0", - "micromatch": "3.1.10", - "resolve-dir": "1.0.1" + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" }, "dependencies": { "expand-tilde": { @@ -4825,7 +4825,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "^1.0.1" } }, "global-modules": { @@ -4834,9 +4834,9 @@ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" } }, "global-prefix": { @@ -4845,11 +4845,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.1" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" } }, "is-glob": { @@ -4858,7 +4858,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } }, "resolve-dir": { @@ -4867,8 +4867,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" } } } @@ -4879,11 +4879,11 @@ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.2" + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" }, "dependencies": { "expand-tilde": { @@ -4892,7 +4892,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "^1.0.1" } } } @@ -4909,10 +4909,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" }, "dependencies": { "circular-json": { @@ -4927,13 +4927,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "globby": { @@ -4942,12 +4942,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "pify": { @@ -4964,8 +4964,8 @@ "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" } }, "follow-redirects": { @@ -4974,7 +4974,7 @@ "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", "dev": true, "requires": { - "debug": "3.1.0" + "debug": "^3.1.0" }, "dependencies": { "debug": { @@ -5000,7 +5000,7 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } }, "foreach": { @@ -5021,9 +5021,9 @@ "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" } }, "formatio": { @@ -5032,7 +5032,7 @@ "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", "dev": true, "requires": { - "samsam": "1.1.2" + "samsam": "~1.1" } }, "forwarded": { @@ -5047,7 +5047,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "^0.2.2" } }, "fresh": { @@ -5068,8 +5068,8 @@ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" } }, "front-matter": { @@ -5078,7 +5078,7 @@ "integrity": "sha1-91mDufL0E75ljJPf172M5AePXNs=", "dev": true, "requires": { - "js-yaml": "3.11.0" + "js-yaml": "^3.4.6" } }, "fs-access": { @@ -5087,7 +5087,7 @@ "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", "dev": true, "requires": { - "null-check": "1.0.0" + "null-check": "^1.0.0" } }, "fs-exists-sync": { @@ -5102,9 +5102,9 @@ "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "3.0.1", - "universalify": "0.1.1" + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" } }, "fs-mkdirp-stream": { @@ -5113,8 +5113,8 @@ "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "through2": "2.0.3" + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" } }, "fs-write-stream-atomic": { @@ -5123,10 +5123,10 @@ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "iferr": "0.1.5", - "imurmurhash": "0.1.4", - "readable-stream": "2.3.6" + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" } }, "fs.realpath": { @@ -5142,8 +5142,8 @@ "dev": true, "optional": true, "requires": { - "nan": "2.10.0", - "node-pre-gyp": "0.10.0" + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" }, "dependencies": { "abbrev": { @@ -5736,10 +5736,10 @@ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" } }, "function-bind": { @@ -5754,14 +5754,14 @@ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.3" + "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" } }, "gaze": { @@ -5771,7 +5771,7 @@ "dev": true, "optional": true, "requires": { - "globule": "1.2.1" + "globule": "^1.0.0" } }, "generate-function": { @@ -5786,7 +5786,7 @@ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "1.0.2" + "is-property": "^1.0.0" } }, "get-caller-file": { @@ -5819,7 +5819,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "glob": { @@ -5828,12 +5828,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-base": { @@ -5842,8 +5842,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "glob-parent": { @@ -5852,7 +5852,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } }, "is-extglob": { @@ -5867,7 +5867,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -5878,8 +5878,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" }, "dependencies": { "is-glob": { @@ -5888,7 +5888,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } } } @@ -5899,16 +5899,16 @@ "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "dev": true, "requires": { - "extend": "3.0.1", - "glob": "7.1.2", - "glob-parent": "3.1.0", - "is-negated-glob": "1.0.0", - "ordered-read-streams": "1.0.1", - "pumpify": "1.5.1", - "readable-stream": "2.3.6", - "remove-trailing-separator": "1.1.0", - "to-absolute-glob": "2.0.2", - "unique-stream": "2.2.1" + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" } }, "glob-to-regexp": { @@ -5923,10 +5923,10 @@ "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==", "dev": true, "requires": { - "async-done": "1.3.1", - "chokidar": "2.0.3", - "just-debounce": "1.0.0", - "object.defaults": "1.1.0" + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" } }, "global-modules": { @@ -5935,8 +5935,8 @@ "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", "dev": true, "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" + "global-prefix": "^0.1.4", + "is-windows": "^0.2.0" }, "dependencies": { "is-windows": { @@ -5953,10 +5953,10 @@ "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "0.2.0", - "which": "1.3.1" + "homedir-polyfill": "^1.0.0", + "ini": "^1.3.4", + "is-windows": "^0.2.0", + "which": "^1.2.12" }, "dependencies": { "is-windows": { @@ -5979,13 +5979,13 @@ "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "dev": true, "requires": { - "array-union": "1.0.2", - "dir-glob": "2.0.0", - "fast-glob": "2.2.2", - "glob": "7.1.2", - "ignore": "3.3.8", - "pify": "3.0.0", - "slash": "1.0.0" + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" } }, "globule": { @@ -5994,9 +5994,9 @@ "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", "dev": true, "requires": { - "glob": "7.1.2", - "lodash": "4.17.10", - "minimatch": "3.0.4" + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" } }, "glogg": { @@ -6005,7 +6005,7 @@ "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", "dev": true, "requires": { - "sparkles": "1.0.1" + "sparkles": "^1.0.0" } }, "gonzales-pe-sl": { @@ -6014,7 +6014,7 @@ "integrity": "sha1-aoaLw4BkXxQf7rBCxvl/zHG1n+Y=", "dev": true, "requires": { - "minimist": "1.1.3" + "minimist": "1.1.x" }, "dependencies": { "minimist": { @@ -6037,10 +6037,10 @@ "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", "dev": true, "requires": { - "glob-watcher": "5.0.1", - "gulp-cli": "2.0.1", - "undertaker": "1.2.0", - "vinyl-fs": "3.0.3" + "glob-watcher": "^5.0.0", + "gulp-cli": "^2.0.0", + "undertaker": "^1.0.0", + "vinyl-fs": "^3.0.0" }, "dependencies": { "camelcase": { @@ -6055,9 +6055,9 @@ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, "gulp-cli": { @@ -6066,24 +6066,24 @@ "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", "dev": true, "requires": { - "ansi-colors": "1.1.0", - "archy": "1.0.0", - "array-sort": "1.0.0", - "color-support": "1.1.3", - "concat-stream": "1.6.2", - "copy-props": "2.0.4", - "fancy-log": "1.3.2", - "gulplog": "1.0.0", - "interpret": "1.1.0", - "isobject": "3.0.1", - "liftoff": "2.5.0", - "matchdep": "2.0.0", - "mute-stdout": "1.0.0", - "pretty-hrtime": "1.0.3", - "replace-homedir": "1.0.0", - "semver-greatest-satisfied-range": "1.1.0", - "v8flags": "3.1.0", - "yargs": "7.1.0" + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^2.5.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" } }, "y18n": { @@ -6098,19 +6098,19 @@ "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", "dev": true, "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "y18n": "3.2.1", - "yargs-parser": "5.0.0" + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" } } } @@ -6121,11 +6121,11 @@ "integrity": "sha512-I+697f6jf+PncdTrqfuwoauxgnLG1yHRg3vlmvDgmJuEnlEHy4meBktJ/oHgfyg4tp6X25wuZqUOraVeVg97wQ==", "dev": true, "requires": { - "get-stream": "3.0.0", - "plugin-error": "0.1.2", - "through2": "2.0.3", - "vinyl": "2.1.0", - "yazl": "2.4.3" + "get-stream": "^3.0.0", + "plugin-error": "^0.1.2", + "through2": "^2.0.1", + "vinyl": "^2.1.0", + "yazl": "^2.1.0" } }, "gulplog": { @@ -6134,7 +6134,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.1" + "glogg": "^1.0.0" } }, "hammerjs": { @@ -6154,10 +6154,10 @@ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" }, "dependencies": { "source-map": { @@ -6166,7 +6166,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } }, "uglify-js": { @@ -6176,9 +6176,9 @@ "dev": true, "optional": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" }, "dependencies": { "source-map": { @@ -6204,8 +6204,8 @@ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" }, "dependencies": { "ajv": { @@ -6214,10 +6214,10 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } } } @@ -6228,7 +6228,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.1.1" } }, "has-ansi": { @@ -6237,7 +6237,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-binary2": { @@ -6275,7 +6275,7 @@ "integrity": "sha1-omHEwqbGZ+DHe3AKfyl8Oe86pYk=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.1" }, "dependencies": { "is-extglob": { @@ -6290,7 +6290,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -6313,9 +6313,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, "has-values": { @@ -6324,8 +6324,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { @@ -6334,7 +6334,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6345,8 +6345,8 @@ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "hash.js": { @@ -6355,8 +6355,8 @@ "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" } }, "he": { @@ -6371,9 +6371,9 @@ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "1.1.5", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, "homedir-polyfill": { @@ -6382,7 +6382,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "parse-passwd": "^1.0.0" } }, "hosted-git-info": { @@ -6397,10 +6397,10 @@ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "dev": true, "requires": { - "inherits": "2.0.3", - "obuf": "1.1.2", - "readable-stream": "2.3.6", - "wbuf": "1.7.3" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, "html-entities": { @@ -6415,13 +6415,13 @@ "integrity": "sha512-Qr2JC9nsjK8oCrEmuB430ZIA8YWbF3D5LSjywD75FTuXmeqacwHgIM8wp3vHYzzPbklSjp53RdmDuzR4ub2HzA==", "dev": true, "requires": { - "camel-case": "3.0.0", - "clean-css": "4.1.11", - "commander": "2.16.0", - "he": "1.1.1", - "param-case": "2.1.1", - "relateurl": "0.2.7", - "uglify-js": "3.4.7" + "camel-case": "3.0.x", + "clean-css": "4.1.x", + "commander": "2.16.x", + "he": "1.1.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" }, "dependencies": { "clean-css": { @@ -6430,7 +6430,7 @@ "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", "dev": true, "requires": { - "source-map": "0.5.6" + "source-map": "0.5.x" } }, "commander": { @@ -6447,12 +6447,12 @@ "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", "dev": true, "requires": { - "html-minifier": "3.5.19", - "loader-utils": "0.2.17", - "lodash": "4.17.10", - "pretty-error": "2.1.1", - "tapable": "1.0.0", - "toposort": "1.0.7", + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", "util.promisify": "1.0.0" }, "dependencies": { @@ -6462,10 +6462,10 @@ "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" } } } @@ -6476,10 +6476,10 @@ "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", "dev": true, "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.1.0", - "domutils": "1.1.6", - "readable-stream": "1.0.34" + "domelementtype": "1", + "domhandler": "2.1", + "domutils": "1.1", + "readable-stream": "1.0" }, "dependencies": { "domutils": { @@ -6488,7 +6488,7 @@ "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", "dev": true, "requires": { - "domelementtype": "1.3.0" + "domelementtype": "1" } }, "isarray": { @@ -6503,10 +6503,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "string_decoder": { @@ -6529,10 +6529,10 @@ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": "1.4.0" + "statuses": ">= 1.4.0 < 2" } }, "http-parser-js": { @@ -6547,9 +6547,9 @@ "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", "dev": true, "requires": { - "eventemitter3": "3.1.0", - "follow-redirects": "1.5.0", - "requires-port": "1.0.0" + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" } }, "http-proxy-middleware": { @@ -6558,10 +6558,10 @@ "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", "dev": true, "requires": { - "http-proxy": "1.17.0", - "is-glob": "4.0.0", - "lodash": "4.17.10", - "micromatch": "3.1.10" + "http-proxy": "^1.16.2", + "is-glob": "^4.0.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9" } }, "http-signature": { @@ -6570,9 +6570,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "https-browserify": { @@ -6587,8 +6587,8 @@ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" + "agent-base": "^4.1.0", + "debug": "^3.1.0" }, "dependencies": { "debug": { @@ -6645,7 +6645,7 @@ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", "dev": true, "requires": { - "import-from": "2.1.0" + "import-from": "^2.1.0" } }, "import-from": { @@ -6654,7 +6654,7 @@ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", "dev": true, "requires": { - "resolve-from": "3.0.0" + "resolve-from": "^3.0.0" } }, "import-local": { @@ -6663,8 +6663,8 @@ "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", "dev": true, "requires": { - "pkg-dir": "2.0.0", - "resolve-cwd": "2.0.0" + "pkg-dir": "^2.0.0", + "resolve-cwd": "^2.0.0" } }, "imurmurhash": { @@ -6686,7 +6686,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "indexof": { @@ -6701,8 +6701,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -6723,19 +6723,19 @@ "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.2.0", - "figures": "1.7.0", - "lodash": "4.17.10", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" }, "dependencies": { "ansi-styles": { @@ -6750,11 +6750,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "supports-color": { @@ -6771,7 +6771,7 @@ "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", "dev": true, "requires": { - "meow": "3.7.0" + "meow": "^3.3.0" } }, "interpret": { @@ -6786,7 +6786,7 @@ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "loose-envify": "1.3.1" + "loose-envify": "^1.0.0" } }, "invert-kv": { @@ -6813,8 +6813,8 @@ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "requires": { - "is-relative": "1.0.0", - "is-windows": "1.0.2" + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" } }, "is-accessor-descriptor": { @@ -6823,7 +6823,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6832,7 +6832,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6849,7 +6849,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.11.0" + "binary-extensions": "^1.0.0" } }, "is-buffer": { @@ -6864,7 +6864,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, "is-callable": { @@ -6879,7 +6879,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6888,7 +6888,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6905,9 +6905,9 @@ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { "kind-of": { @@ -6936,7 +6936,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "^2.0.0" } }, "is-extendable": { @@ -6957,7 +6957,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-fullwidth-code-point": { @@ -6966,7 +6966,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-glob": { @@ -6975,7 +6975,7 @@ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.1" } }, "is-my-ip-valid": { @@ -6990,11 +6990,11 @@ "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "dev": true, "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "is-my-ip-valid": "1.0.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" } }, "is-negated-glob": { @@ -7009,7 +7009,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -7018,7 +7018,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -7029,7 +7029,7 @@ "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "dev": true, "requires": { - "is-number": "4.0.0" + "is-number": "^4.0.0" }, "dependencies": { "is-number": { @@ -7052,7 +7052,7 @@ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.1" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -7061,7 +7061,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-plain-object": { @@ -7070,7 +7070,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "is-posix-bracket": { @@ -7097,7 +7097,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "1.0.3" + "has": "^1.0.1" } }, "is-relative": { @@ -7106,7 +7106,7 @@ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "requires": { - "is-unc-path": "1.0.0" + "is-unc-path": "^1.0.0" } }, "is-resolvable": { @@ -7145,7 +7145,7 @@ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "requires": { - "unc-path-regex": "0.1.2" + "unc-path-regex": "^0.1.2" } }, "is-utf8": { @@ -7184,7 +7184,7 @@ "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", "dev": true, "requires": { - "buffer-alloc": "1.2.0" + "buffer-alloc": "^1.2.0" } }, "isexe": { @@ -7211,20 +7211,20 @@ "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.11.0", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.1", - "wordwrap": "1.0.0" + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" }, "dependencies": { "esprima": { @@ -7239,11 +7239,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "has-flag": { @@ -7264,7 +7264,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -7275,18 +7275,18 @@ "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", "dev": true, "requires": { - "async": "2.6.1", - "compare-versions": "3.3.0", - "fileset": "2.0.3", - "istanbul-lib-coverage": "1.2.0", - "istanbul-lib-hook": "1.2.1", - "istanbul-lib-instrument": "1.10.1", - "istanbul-lib-report": "1.1.4", - "istanbul-lib-source-maps": "1.2.5", - "istanbul-reports": "1.3.0", - "js-yaml": "3.11.0", - "mkdirp": "0.5.1", - "once": "1.4.0" + "async": "^2.1.4", + "compare-versions": "^3.1.0", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.0", + "istanbul-lib-hook": "^1.2.0", + "istanbul-lib-instrument": "^1.10.1", + "istanbul-lib-report": "^1.1.4", + "istanbul-lib-source-maps": "^1.2.4", + "istanbul-reports": "^1.3.0", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" }, "dependencies": { "async": { @@ -7295,7 +7295,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "4.17.10" + "lodash": "^4.17.10" } } } @@ -7306,10 +7306,10 @@ "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", "dev": true, "requires": { - "convert-source-map": "1.5.1", - "istanbul-lib-instrument": "1.10.1", - "loader-utils": "1.1.0", - "schema-utils": "0.3.0" + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" }, "dependencies": { "ajv": { @@ -7318,10 +7318,10 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "schema-utils": { @@ -7330,7 +7330,7 @@ "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", "dev": true, "requires": { - "ajv": "5.5.2" + "ajv": "^5.0.0" } } } @@ -7347,7 +7347,7 @@ "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", "dev": true, "requires": { - "append-transform": "1.0.0" + "append-transform": "^1.0.0" } }, "istanbul-lib-instrument": { @@ -7356,13 +7356,13 @@ "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", "dev": true, "requires": { - "babel-generator": "6.26.1", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "istanbul-lib-coverage": "1.2.0", - "semver": "5.5.0" + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.0", + "semver": "^5.3.0" } }, "istanbul-lib-report": { @@ -7371,10 +7371,10 @@ "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", "dev": true, "requires": { - "istanbul-lib-coverage": "1.2.0", - "mkdirp": "0.5.1", - "path-parse": "1.0.5", - "supports-color": "3.2.3" + "istanbul-lib-coverage": "^1.2.0", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" }, "dependencies": { "has-flag": { @@ -7389,7 +7389,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -7400,11 +7400,11 @@ "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", "dev": true, "requires": { - "debug": "3.1.0", - "istanbul-lib-coverage": "1.2.0", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "source-map": "0.5.6" + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.0", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" }, "dependencies": { "debug": { @@ -7424,7 +7424,7 @@ "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", "dev": true, "requires": { - "handlebars": "4.0.11" + "handlebars": "^4.0.3" } }, "jasmine": { @@ -7433,9 +7433,9 @@ "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", "dev": true, "requires": { - "exit": "0.1.2", - "glob": "7.1.2", - "jasmine-core": "2.8.0" + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" }, "dependencies": { "jasmine-core": { @@ -7458,7 +7458,7 @@ "integrity": "sha1-k8zC3MQQKMXd1GBlWAdIOfLe6qg=", "dev": true, "requires": { - "diff": "3.5.0" + "diff": "^3.2.0" } }, "jasmine-spec-reporter": { @@ -7494,8 +7494,8 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "jsbn": { @@ -7535,7 +7535,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stringify-safe": { @@ -7562,7 +7562,7 @@ "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" } }, "jsonify": { @@ -7595,11 +7595,11 @@ "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", "dev": true, "requires": { - "core-js": "2.3.0", - "es6-promise": "3.0.2", - "lie": "3.1.1", - "pako": "1.0.6", - "readable-stream": "2.0.6" + "core-js": "~2.3.0", + "es6-promise": "~3.0.2", + "lie": "~3.1.0", + "pako": "~1.0.2", + "readable-stream": "~2.0.6" }, "dependencies": { "core-js": { @@ -7626,12 +7626,12 @@ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -7654,31 +7654,31 @@ "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==", "dev": true, "requires": { - "bluebird": "3.5.1", - "body-parser": "1.18.2", - "chokidar": "2.0.3", - "colors": "1.1.2", - "combine-lists": "1.0.1", - "connect": "3.6.6", - "core-js": "2.5.7", - "di": "0.0.1", - "dom-serialize": "2.2.1", - "expand-braces": "0.1.2", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "http-proxy": "1.17.0", - "isbinaryfile": "3.0.3", - "lodash": "4.17.10", - "log4js": "3.0.5", - "mime": "2.3.1", - "minimatch": "3.0.4", - "optimist": "0.6.1", - "qjobs": "1.2.0", - "range-parser": "1.2.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.2", + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.4", + "log4js": "^3.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", "socket.io": "2.1.1", - "source-map": "0.6.1", + "source-map": "^0.6.1", "tmp": "0.0.33", "useragent": "2.2.1" }, @@ -7703,8 +7703,8 @@ "integrity": "sha1-IWh5xorATY1RQOmWGboEtZr9Rs8=", "dev": true, "requires": { - "fs-access": "1.0.1", - "which": "1.3.1" + "fs-access": "^1.0.0", + "which": "^1.2.1" } }, "karma-cli": { @@ -7713,7 +7713,7 @@ "integrity": "sha1-rmw8WKMTodALRRZMRVubhs4X+WA=", "dev": true, "requires": { - "resolve": "1.7.1" + "resolve": "^1.1.6" } }, "karma-coverage-istanbul-reporter": { @@ -7722,8 +7722,8 @@ "integrity": "sha512-UcgrHkFehI5+ivMouD8NH/UOHiX4oCAtwaANylzPFdcAuD52fnCUuelacq2gh8tZ4ydhU3+xiXofSq7j5Ehygw==", "dev": true, "requires": { - "istanbul-api": "1.3.1", - "minimatch": "3.0.4" + "istanbul-api": "^1.3.1", + "minimatch": "^3.0.4" } }, "karma-jasmine": { @@ -7744,7 +7744,7 @@ "integrity": "sha512-HcPqdAusNez/ywa+biN4EphGz62MmQyPggUsDfsHqa7tSe4jdsxgvTKuDfIazjL+IOxpVWyT7Pr4dhAV+sxX5Q==", "dev": true, "requires": { - "source-map-support": "0.5.6" + "source-map-support": "^0.5.5" } }, "karma-spec-reporter": { @@ -7753,7 +7753,7 @@ "integrity": "sha1-SDDccUihVcfXoYbmMjOaDYD63sM=", "dev": true, "requires": { - "colors": "1.1.2" + "colors": "^1.1.2" } }, "killable": { @@ -7774,7 +7774,7 @@ "integrity": "sha1-PTvNhgDnv971MjHHOf8FOu1WDkQ=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.11" } }, "known-css-properties": { @@ -7789,8 +7789,8 @@ "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", "dev": true, "requires": { - "default-resolution": "2.0.0", - "es6-weak-map": "2.0.2" + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" } }, "lazy-cache": { @@ -7805,7 +7805,7 @@ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dev": true, "requires": { - "readable-stream": "2.3.6" + "readable-stream": "^2.0.5" } }, "lcid": { @@ -7814,7 +7814,7 @@ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "1.0.0" + "invert-kv": "^1.0.0" } }, "lead": { @@ -7823,7 +7823,7 @@ "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", "dev": true, "requires": { - "flush-write-stream": "1.0.3" + "flush-write-stream": "^1.0.2" } }, "leb": { @@ -7838,15 +7838,15 @@ "integrity": "sha512-8HFGuWmL3FhQR0aH89escFNBQH/nEiYPP2ltDFdQw2chE28Yx2E3lhAIq9Y2saYwLSwa699s4dBVEfCY8Drf7Q==", "dev": true, "requires": { - "clone": "2.1.2", - "errno": "0.1.7", - "graceful-fs": "4.1.11", - "image-size": "0.5.5", - "mime": "1.6.0", - "mkdirp": "0.5.1", - "promise": "7.3.1", - "request": "2.87.0", - "source-map": "0.6.1" + "clone": "^2.1.2", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.4.1", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "^2.83.0", + "source-map": "~0.6.0" }, "dependencies": { "clone": { @@ -7870,9 +7870,9 @@ "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==", "dev": true, "requires": { - "clone": "2.1.1", - "loader-utils": "1.1.0", - "pify": "3.0.0" + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^3.0.0" } }, "levn": { @@ -7881,8 +7881,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "license-webpack-plugin": { @@ -7891,7 +7891,7 @@ "integrity": "sha512-iwuNFMWbXS76WiQXJBTs8/7Tby4NQnY8AIkBMuJG5El79UT8zWrJQMfpW+KRXt4Y2Bs5uk+Myg/MO7ROSF8jzA==", "dev": true, "requires": { - "ejs": "2.6.1" + "ejs": "^2.5.7" } }, "lie": { @@ -7900,7 +7900,7 @@ "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", "dev": true, "requires": { - "immediate": "3.0.6" + "immediate": "~3.0.5" } }, "liftoff": { @@ -7909,14 +7909,14 @@ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.7.1" + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" } }, "load-json-file": { @@ -7925,11 +7925,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, "dependencies": { "pify": { @@ -7952,9 +7952,9 @@ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" } }, "locate-path": { @@ -7963,8 +7963,8 @@ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, "lodash": { @@ -8004,6 +8004,11 @@ "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", "dev": true }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==" + }, "lodash.mergewith": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", @@ -8023,7 +8028,7 @@ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { - "chalk": "2.2.2" + "chalk": "^2.0.1" } }, "log4js": { @@ -8032,10 +8037,10 @@ "integrity": "sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==", "dev": true, "requires": { - "circular-json": "0.5.5", - "date-format": "1.2.0", - "debug": "3.2.5", - "rfdc": "1.1.2", + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", "streamroller": "0.7.0" }, "dependencies": { @@ -8051,7 +8056,7 @@ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "2.1.1" + "ms": "^2.1.1" } }, "ms": { @@ -8074,13 +8079,13 @@ "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", "dev": true, "requires": { - "es6-symbol": "3.1.1", - "object.assign": "4.1.0" + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" } }, "lolex": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "resolved": "http://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, @@ -8102,7 +8107,7 @@ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "3.0.2" + "js-tokens": "^3.0.0" } }, "loud-rejection": { @@ -8111,8 +8116,8 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" } }, "lower-case": { @@ -8127,8 +8132,8 @@ "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "make-dir": { @@ -8137,7 +8142,7 @@ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" } }, "make-error": { @@ -8152,7 +8157,7 @@ "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.2" } }, "map-cache": { @@ -8169,7 +8174,7 @@ }, "map-stream": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "resolved": "http://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, @@ -8179,7 +8184,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "^1.0.0" } }, "matchdep": { @@ -8188,9 +8193,9 @@ "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "dev": true, "requires": { - "findup-sync": "2.0.0", - "micromatch": "3.1.10", - "resolve": "1.7.1", + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", "stack-trace": "0.0.10" } }, @@ -8200,15 +8205,15 @@ "integrity": "sha1-Vte36xgDPwz5vFLrIJD6x9weifo=", "dev": true, "requires": { - "arr-union": "3.1.0", - "async-array-reduce": "0.2.1", - "extend-shallow": "2.0.1", - "fs-exists-sync": "0.1.0", - "glob": "7.1.2", - "has-glob": "0.1.1", - "is-valid-glob": "0.3.0", - "lazy-cache": "2.0.2", - "resolve-dir": "0.1.1" + "arr-union": "^3.1.0", + "async-array-reduce": "^0.2.0", + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "glob": "^7.0.5", + "has-glob": "^0.1.1", + "is-valid-glob": "^0.3.0", + "lazy-cache": "^2.0.1", + "resolve-dir": "^0.1.0" }, "dependencies": { "extend-shallow": { @@ -8217,7 +8222,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "lazy-cache": { @@ -8226,7 +8231,7 @@ "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", "dev": true, "requires": { - "set-getter": "0.1.0" + "set-getter": "^0.1.0" } } } @@ -8243,8 +8248,8 @@ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "media-typer": { @@ -8259,7 +8264,7 @@ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "^1.0.0" } }, "memory-fs": { @@ -8268,8 +8273,8 @@ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.6" + "errno": "^0.1.3", + "readable-stream": "^2.0.1" } }, "meow": { @@ -8278,16 +8283,16 @@ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" }, "dependencies": { "minimist": { @@ -8328,19 +8333,19 @@ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "miller-rabin": { @@ -8349,8 +8354,8 @@ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" } }, "mime": { @@ -8371,7 +8376,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "mimic-fn": { @@ -8386,9 +8391,9 @@ "integrity": "sha512-XWuB3G61Rtasq/gLe7cp5cuozehE6hN+E4sxCamRR/WDiHTg+f7ZIAS024r8UJQffY+e2gGELXQZgQoFDfNDCg==", "dev": true, "requires": { - "@webpack-contrib/schema-utils": "1.0.0-beta.0", - "loader-utils": "1.1.0", - "webpack-sources": "1.1.0" + "@webpack-contrib/schema-utils": "^1.0.0-beta.0", + "loader-utils": "^1.1.0", + "webpack-sources": "^1.1.0" } }, "minimalistic-assert": { @@ -8409,7 +8414,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -8424,16 +8429,16 @@ "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", "dev": true, "requires": { - "concat-stream": "1.6.2", - "duplexify": "3.6.0", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.3", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "2.0.1", - "pumpify": "1.5.1", - "stream-each": "1.2.3", - "through2": "2.0.3" + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" } }, "mixin-deep": { @@ -8442,8 +8447,8 @@ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -8452,7 +8457,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -8463,8 +8468,8 @@ "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", "dev": true, "requires": { - "for-in": "0.1.8", - "is-extendable": "0.1.1" + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" }, "dependencies": { "for-in": { @@ -8501,12 +8506,12 @@ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { - "aproba": "1.2.0", - "copy-concurrently": "1.0.5", - "fs-write-stream-atomic": "1.0.10", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" } }, "ms": { @@ -8521,8 +8526,8 @@ "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", "dev": true, "requires": { - "dns-packet": "1.3.1", - "thunky": "1.0.2" + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" } }, "multicast-dns-service-types": { @@ -8556,18 +8561,18 @@ "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-odd": "^2.0.0", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" } }, "negotiator": { @@ -8594,7 +8599,15 @@ "integrity": "sha512-IO2zBWMAyAWZgK6zbPhmR3tNRgW+jfi/Z+Xkvaa42w6eYNQ8bEwYv7uxZo/3MQJ5RglxZ+6KsDLXPzjN+ZUEZw==", "dev": true, "requires": { - "deep-freeze-strict": "1.1.1" + "deep-freeze-strict": "^1.1.1" + } + }, + "ngrx-store-localstorage": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ngrx-store-localstorage/-/ngrx-store-localstorage-7.0.0.tgz", + "integrity": "sha512-Bpu4C1tA4L3tyD0x4rf+ff52ZAhQskWy7AWr7iREmJfh89sYA1bsRjWNr0PL1gRmEP+1l7V2cUKCH/DhLCDInQ==", + "requires": { + "lodash.merge": "^4.6.1" } }, "ngrx-store-logger": { @@ -8607,7 +8620,7 @@ "resolved": "https://registry.npmjs.org/ngx-moment/-/ngx-moment-3.1.0.tgz", "integrity": "sha512-liX6iTfOY0XyI3rUuWNgGpgxoeD+DFaAl7UJ/ejl9Ama5cXzw8L1Eft6UQLUo1d80kjNMc6AL+L19CPMvUQ/BA==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "no-case": { @@ -8616,7 +8629,7 @@ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "requires": { - "lower-case": "1.1.4" + "lower-case": "^1.1.1" } }, "node-forge": { @@ -8638,18 +8651,18 @@ "dev": true, "optional": true, "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.5", - "request": "2.87.0", - "rimraf": "2.6.2", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.3.1" + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" }, "dependencies": { "semver": { @@ -8667,28 +8680,28 @@ "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", "dev": true, "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.2.0", - "events": "1.1.1", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.6", - "stream-browserify": "2.0.1", - "stream-http": "2.8.3", - "string_decoder": "1.1.1", - "timers-browserify": "2.0.10", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", + "url": "^0.11.0", + "util": "^0.10.3", "vm-browserify": "0.0.4" }, "dependencies": { @@ -8707,25 +8720,25 @@ "dev": true, "optional": true, "requires": { - "async-foreach": "0.1.3", - "chalk": "1.1.3", - "cross-spawn": "3.0.1", - "gaze": "1.1.3", - "get-stdin": "4.0.1", - "glob": "7.1.2", - "in-publish": "2.0.0", - "lodash.assign": "4.2.0", - "lodash.clonedeep": "4.5.0", - "lodash.mergewith": "4.6.1", - "meow": "3.7.0", - "mkdirp": "0.5.1", - "nan": "2.10.0", - "node-gyp": "3.8.0", - "npmlog": "4.1.2", + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash.assign": "^4.2.0", + "lodash.clonedeep": "^4.3.2", + "lodash.mergewith": "^4.6.0", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.10.0", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", "request": "2.87.0", - "sass-graph": "2.2.4", - "stdout-stream": "1.4.0", - "true-case-path": "1.0.2" + "sass-graph": "^2.2.4", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" }, "dependencies": { "ansi-styles": { @@ -8742,11 +8755,11 @@ "dev": true, "optional": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "supports-color": { @@ -8764,7 +8777,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "1" } }, "normalize-package-data": { @@ -8773,10 +8786,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.3" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -8785,7 +8798,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" } }, "normalize-range": { @@ -8805,7 +8818,7 @@ "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.3.2" } }, "npm-package-arg": { @@ -8814,10 +8827,10 @@ "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==", "dev": true, "requires": { - "hosted-git-info": "2.6.0", - "osenv": "0.1.5", - "semver": "5.5.0", - "validate-npm-package-name": "3.0.0" + "hosted-git-info": "^2.6.0", + "osenv": "^0.1.5", + "semver": "^5.5.0", + "validate-npm-package-name": "^3.0.0" } }, "npm-registry-client": { @@ -8826,18 +8839,18 @@ "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==", "dev": true, "requires": { - "concat-stream": "1.6.2", - "graceful-fs": "4.1.11", - "normalize-package-data": "2.4.0", - "npm-package-arg": "6.1.0", - "npmlog": "4.1.2", - "once": "1.4.0", - "request": "2.87.0", - "retry": "0.10.1", - "safe-buffer": "5.1.2", - "semver": "5.5.0", - "slide": "1.1.6", - "ssri": "5.3.0" + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "safe-buffer": "^5.1.1", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^5.2.4" } }, "npm-run-path": { @@ -8846,7 +8859,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "2.0.1" + "path-key": "^2.0.0" } }, "npmlog": { @@ -8855,10 +8868,10 @@ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { - "are-we-there-yet": "1.1.5", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "nth-check": { @@ -8867,7 +8880,7 @@ "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", "dev": true, "requires": { - "boolbase": "1.0.0" + "boolbase": "~1.0.0" } }, "null-check": { @@ -8912,9 +8925,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { "define-property": { @@ -8923,7 +8936,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "kind-of": { @@ -8932,7 +8945,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -8949,7 +8962,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.0" } }, "object.assign": { @@ -8958,10 +8971,10 @@ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "has-symbols": "1.0.0", - "object-keys": "1.0.11" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, "object.defaults": { @@ -8970,10 +8983,10 @@ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" } }, "object.getownpropertydescriptors": { @@ -8982,8 +8995,8 @@ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.12.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" } }, "object.map": { @@ -8992,8 +9005,8 @@ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.1" + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" } }, "object.omit": { @@ -9002,8 +9015,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" }, "dependencies": { "for-own": { @@ -9012,7 +9025,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } } } @@ -9023,7 +9036,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, "object.reduce": { @@ -9032,8 +9045,8 @@ "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", "dev": true, "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.1" + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" } }, "obuf": { @@ -9063,7 +9076,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -9078,7 +9091,7 @@ "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", "dev": true, "requires": { - "is-wsl": "1.1.0" + "is-wsl": "^1.1.0" } }, "optimist": { @@ -9087,8 +9100,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" }, "dependencies": { "wordwrap": { @@ -9105,12 +9118,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" } }, "ordered-read-streams": { @@ -9119,7 +9132,7 @@ "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", "dev": true, "requires": { - "readable-stream": "2.3.6" + "readable-stream": "^2.0.1" } }, "original": { @@ -9128,7 +9141,7 @@ "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", "dev": true, "requires": { - "url-parse": "1.4.3" + "url-parse": "^1.4.3" } }, "os-browserify": { @@ -9149,7 +9162,7 @@ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "1.0.0" + "lcid": "^1.0.0" } }, "os-tmpdir": { @@ -9164,8 +9177,8 @@ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "p-finally": { @@ -9180,7 +9193,7 @@ "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "dev": true, "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { @@ -9189,7 +9202,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.2.0" + "p-limit": "^1.1.0" } }, "p-map": { @@ -9216,9 +9229,9 @@ "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", "dev": true, "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.6" + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" } }, "param-case": { @@ -9227,7 +9240,7 @@ "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", "dev": true, "requires": { - "no-case": "2.3.2" + "no-case": "^2.2.0" } }, "parse-asn1": { @@ -9236,11 +9249,11 @@ "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "dev": true, "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.16" + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" } }, "parse-filepath": { @@ -9249,9 +9262,9 @@ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" } }, "parse-glob": { @@ -9260,10 +9273,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "is-extglob": { @@ -9278,7 +9291,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -9289,7 +9302,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "parse-passwd": { @@ -9310,7 +9323,7 @@ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseuri": { @@ -9319,7 +9332,7 @@ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseurl": { @@ -9340,8 +9353,8 @@ "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", "dev": true, "requires": { - "process": "0.11.10", - "util": "0.10.3" + "process": "^0.11.1", + "util": "^0.10.3" } }, "path-browserify": { @@ -9392,7 +9405,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "0.1.2" + "path-root-regex": "^0.1.0" } }, "path-root-regex": { @@ -9413,16 +9426,16 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" } }, "pause-stream": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { - "through": "2.3.8" + "through": "~2.3" } }, "pbkdf2": { @@ -9431,11 +9444,11 @@ "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", "dev": true, "requires": { - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "performance-now": { @@ -9462,7 +9475,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pkg-dir": { @@ -9471,7 +9484,7 @@ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "2.1.0" + "find-up": "^2.1.0" } }, "plugin-error": { @@ -9480,11 +9493,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "0.1.1", - "ansi-red": "0.1.1", - "arr-diff": "1.1.0", - "arr-union": "2.1.0", - "extend-shallow": "1.1.4" + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" }, "dependencies": { "arr-diff": { @@ -9493,8 +9506,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "array-slice": "0.2.3" + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" } }, "arr-union": { @@ -9515,7 +9528,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "1.1.0" + "kind-of": "^1.1.0" } }, "kind-of": { @@ -9538,9 +9551,9 @@ "integrity": "sha512-icBXCFQxzlK2PMepOM0QeEdPPFSLAaXXeuKOv5AClJlMy1oVCBrkDGJ12IZYesI/BF8mpeVco3vRCmgeBb4+hw==", "dev": true, "requires": { - "async": "1.5.2", - "debug": "2.6.9", - "mkdirp": "0.5.1" + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" } }, "posix-character-classes": { @@ -9555,9 +9568,9 @@ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", "dev": true, "requires": { - "chalk": "2.4.1", - "source-map": "0.6.1", - "supports-color": "5.4.0" + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" }, "dependencies": { "chalk": { @@ -9566,9 +9579,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "source-map": { @@ -9585,10 +9598,10 @@ "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==", "dev": true, "requires": { - "postcss": "6.0.23", - "postcss-value-parser": "3.3.0", - "read-cache": "1.0.0", - "resolve": "1.7.1" + "postcss": "^6.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" } }, "postcss-load-config": { @@ -9597,8 +9610,8 @@ "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", "dev": true, "requires": { - "cosmiconfig": "4.0.0", - "import-cwd": "2.1.0" + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" } }, "postcss-loader": { @@ -9607,10 +9620,10 @@ "integrity": "sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg==", "dev": true, "requires": { - "loader-utils": "1.1.0", - "postcss": "6.0.23", - "postcss-load-config": "2.0.0", - "schema-utils": "0.4.7" + "loader-utils": "^1.1.0", + "postcss": "^6.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^0.4.0" } }, "postcss-url": { @@ -9619,11 +9632,11 @@ "integrity": "sha512-QMV5mA+pCYZQcUEPQkmor9vcPQ2MT+Ipuu8qdi1gVxbNiIiErEGft+eny1ak19qALoBkccS5AHaCaCDzh7b9MA==", "dev": true, "requires": { - "mime": "1.6.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "postcss": "6.0.23", - "xxhashjs": "0.2.2" + "mime": "^1.4.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.0", + "postcss": "^6.0.1", + "xxhashjs": "^0.2.1" } }, "postcss-value-parser": { @@ -9650,8 +9663,8 @@ "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", "dev": true, "requires": { - "renderkid": "2.0.1", - "utila": "0.4.0" + "renderkid": "^2.0.1", + "utila": "~0.4" } }, "pretty-hrtime": { @@ -9685,7 +9698,7 @@ "dev": true, "optional": true, "requires": { - "asap": "2.0.6" + "asap": "~2.0.3" } }, "promise-inflight": { @@ -9700,22 +9713,22 @@ "integrity": "sha512-6TSYqMhUUzxr4/wN0ttSISqPMKvcVRXF4k8jOEpGWD8OioLak4KLgfzHK9FJ49IrjzRrZ+Mx1q2Op8Rk0zEcnQ==", "dev": true, "requires": { - "@types/node": "6.0.111", - "@types/q": "0.0.32", - "@types/selenium-webdriver": "3.0.10", - "blocking-proxy": "1.0.1", - "browserstack": "1.5.1", - "chalk": "1.1.3", - "glob": "7.1.2", + "@types/node": "^6.0.46", + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", "jasmine": "2.8.0", - "jasminewd2": "2.2.0", - "optimist": "0.6.1", + "jasminewd2": "^2.1.0", + "optimist": "~0.6.0", "q": "1.4.1", - "saucelabs": "1.5.0", + "saucelabs": "^1.5.0", "selenium-webdriver": "3.6.0", - "source-map-support": "0.4.18", + "source-map-support": "~0.4.0", "webdriver-js-extender": "2.0.0", - "webdriver-manager": "12.1.0" + "webdriver-manager": "^12.0.6" }, "dependencies": { "ansi-styles": { @@ -9730,11 +9743,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "del": { @@ -9743,13 +9756,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "globby": { @@ -9758,12 +9771,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "minimist": { @@ -9790,7 +9803,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "0.5.6" + "source-map": "^0.5.6" } }, "supports-color": { @@ -9805,17 +9818,17 @@ "integrity": "sha512-oEc5fmkpz6Yh6udhwir5m0eN5mgRPq9P/NU5YWuT3Up5slt6Zz+znhLU7q4+8rwCZz/Qq3Fgpr/4oao7NPCm2A==", "dev": true, "requires": { - "adm-zip": "0.4.11", - "chalk": "1.1.3", - "del": "2.2.2", - "glob": "7.1.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "q": "1.4.1", - "request": "2.87.0", - "rimraf": "2.6.2", - "semver": "5.5.0", - "xml2js": "0.4.19" + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" } } } @@ -9826,7 +9839,7 @@ "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", "dev": true, "requires": { - "forwarded": "0.1.2", + "forwarded": "~0.1.2", "ipaddr.js": "1.8.0" } }, @@ -9842,7 +9855,7 @@ "integrity": "sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=", "dev": true, "requires": { - "table-parser": "0.1.3" + "table-parser": "^0.1.3" } }, "ps-tree": { @@ -9851,7 +9864,7 @@ "integrity": "sha512-kef7fYYSKVqQffmzTMsVcUD1ObNJMp8sNSmHGlGKsZQyL/ht9MZKk86u0Rd1NhpTOAuhqwKCLLpktwkqz+MF8A==", "dev": true, "requires": { - "event-stream": "3.3.4" + "event-stream": "=3.3.4" } }, "pseudomap": { @@ -9866,11 +9879,11 @@ "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "parse-asn1": "5.1.1", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" } }, "pump": { @@ -9879,8 +9892,8 @@ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, "pumpify": { @@ -9889,9 +9902,9 @@ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "requires": { - "duplexify": "3.6.0", - "inherits": "2.0.3", - "pump": "2.0.1" + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, "punycode": { @@ -9942,9 +9955,9 @@ "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", "dev": true, "requires": { - "is-number": "4.0.0", - "kind-of": "6.0.2", - "math-random": "1.0.1" + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" }, "dependencies": { "is-number": { @@ -9961,7 +9974,7 @@ "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.1.0" } }, "randomfill": { @@ -9970,8 +9983,8 @@ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.2" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, "range-parser": { @@ -10007,7 +10020,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.4.0" + "statuses": ">= 1.3.1 < 2" } }, "setprototypeof": { @@ -10030,7 +10043,7 @@ "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", "dev": true, "requires": { - "pify": "2.3.0" + "pify": "^2.3.0" }, "dependencies": { "pify": { @@ -10047,9 +10060,9 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" }, "dependencies": { "path-type": { @@ -10058,9 +10071,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "pify": { @@ -10077,8 +10090,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" }, "dependencies": { "find-up": { @@ -10087,8 +10100,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "path-exists": { @@ -10097,7 +10110,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "^2.0.0" } } } @@ -10108,13 +10121,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "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" } }, "readdirp": { @@ -10123,10 +10136,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.6", - "set-immediate-shim": "1.0.1" + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" } }, "readline2": { @@ -10135,8 +10148,8 @@ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", "mute-stream": "0.0.5" } }, @@ -10146,7 +10159,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.7.1" + "resolve": "^1.1.6" } }, "redent": { @@ -10155,8 +10168,8 @@ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" } }, "reflect-metadata": { @@ -10183,7 +10196,7 @@ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { - "is-equal-shallow": "0.1.3" + "is-equal-shallow": "^0.1.3" } }, "regex-not": { @@ -10192,8 +10205,8 @@ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, "regexpu-core": { @@ -10202,9 +10215,9 @@ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", "dev": true, "requires": { - "regenerate": "1.4.0", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" } }, "regjsgen": { @@ -10219,7 +10232,7 @@ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { - "jsesc": "0.5.0" + "jsesc": "~0.5.0" }, "dependencies": { "jsesc": { @@ -10242,8 +10255,8 @@ "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", "dev": true, "requires": { - "is-buffer": "1.1.6", - "is-utf8": "0.2.1" + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" } }, "remove-bom-stream": { @@ -10252,9 +10265,9 @@ "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", "dev": true, "requires": { - "remove-bom-buffer": "3.0.0", - "safe-buffer": "5.1.2", - "through2": "2.0.3" + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" } }, "remove-trailing-separator": { @@ -10269,11 +10282,11 @@ "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", "dev": true, "requires": { - "css-select": "1.2.0", - "dom-converter": "0.1.4", - "htmlparser2": "3.3.0", - "strip-ansi": "3.0.1", - "utila": "0.3.3" + "css-select": "^1.1.0", + "dom-converter": "~0.1", + "htmlparser2": "~3.3.0", + "strip-ansi": "^3.0.0", + "utila": "~0.3" }, "dependencies": { "utila": { @@ -10302,7 +10315,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "replace-ext": { @@ -10317,9 +10330,9 @@ "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1", - "is-absolute": "1.0.0", - "remove-trailing-separator": "1.1.0" + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" } }, "replace-in-file": { @@ -10328,9 +10341,9 @@ "integrity": "sha512-fto9Ooab00CniGkSjRCZCamER7P5S4mZHQ4w4dLd09nwP3FtFfjUJh8/OVC/In4ki5MEy+dYO5v9r7rtq2DrYQ==", "dev": true, "requires": { - "chalk": "2.4.1", - "glob": "7.1.2", - "yargs": "11.1.0" + "chalk": "^2.3.2", + "glob": "^7.1.2", + "yargs": "^11.0.0" }, "dependencies": { "ansi-regex": { @@ -10351,9 +10364,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "cliui": { @@ -10362,9 +10375,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" } }, "is-fullwidth-code-point": { @@ -10379,9 +10392,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "string-width": { @@ -10390,8 +10403,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -10400,7 +10413,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "which-module": { @@ -10421,18 +10434,18 @@ "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" } }, "yargs-parser": { @@ -10441,7 +10454,7 @@ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } } } @@ -10452,26 +10465,26 @@ "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "dev": true, "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.7.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.2", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" } }, "request-promise-core": { @@ -10480,7 +10493,7 @@ "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", "dev": true, "requires": { - "lodash": "4.17.10" + "lodash": "^4.13.1" } }, "request-promise-native": { @@ -10490,8 +10503,8 @@ "dev": true, "requires": { "request-promise-core": "1.1.1", - "stealthy-require": "1.1.1", - "tough-cookie": "2.3.4" + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" } }, "require-directory": { @@ -10518,8 +10531,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" }, "dependencies": { "resolve-from": { @@ -10547,7 +10560,7 @@ "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "resolve-cwd": { @@ -10556,7 +10569,7 @@ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "3.0.0" + "resolve-from": "^3.0.0" } }, "resolve-dir": { @@ -10565,8 +10578,8 @@ "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", "dev": true, "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" + "expand-tilde": "^1.2.2", + "global-modules": "^0.2.3" } }, "resolve-from": { @@ -10581,7 +10594,7 @@ "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", "dev": true, "requires": { - "value-or-function": "3.0.0" + "value-or-function": "^3.0.0" } }, "resolve-url": { @@ -10596,8 +10609,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } }, "ret": { @@ -10625,7 +10638,7 @@ "dev": true, "optional": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { @@ -10634,7 +10647,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "ripemd160": { @@ -10643,8 +10656,8 @@ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "run-async": { @@ -10653,7 +10666,7 @@ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.3.0" } }, "run-queue": { @@ -10662,7 +10675,7 @@ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "requires": { - "aproba": "1.2.0" + "aproba": "^1.1.1" } }, "rx-lite": { @@ -10676,7 +10689,7 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.0.tgz", "integrity": "sha512-qBzf5uu6eOKiCZuAE0SgZ0/Qp+l54oeVxFfC2t+mJ2SFI6IB8gmMdJHs5DUMu5kqifqcCtsKS2XHjhZu6RKvAw==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "rxjs-spy": { @@ -10684,11 +10697,11 @@ "resolved": "https://registry.npmjs.org/rxjs-spy/-/rxjs-spy-7.0.2.tgz", "integrity": "sha512-rSzEEQLH07FPBqmxIC8oeI2Z7tWibvxKxybcKtcc6Cj8Tz178ySDgzgOkoct8dAz5IE/H2jrR2/l+ZYYfpuEXw==", "requires": { - "@types/circular-json": "0.4.0", - "@types/stacktrace-js": "0.0.32", - "circular-json": "0.5.4", - "error-stack-parser": "2.0.1", - "stacktrace-gps": "3.0.2" + "@types/circular-json": "^0.4.0", + "@types/stacktrace-js": "^0.0.32", + "circular-json": "^0.5.0", + "error-stack-parser": "^2.0.1", + "stacktrace-gps": "^3.0.2" } }, "rxjs-tslint": { @@ -10697,10 +10710,10 @@ "integrity": "sha512-odvEAx6VoZSJs5o9gWZ7SxgTuS8ldq0mr4qnprbr6flNtIt4DtNJSYJpBK0WEy0o+f1oe92XVHrmgco1e7Cpdw==", "dev": true, "requires": { - "chalk": "2.4.1", - "optimist": "0.6.1", - "tslint": "5.10.0", - "tsutils": "2.27.1" + "chalk": "^2.4.0", + "optimist": "^0.6.1", + "tslint": "^5.9.1", + "tsutils": "^2.25.0" }, "dependencies": { "chalk": { @@ -10709,9 +10722,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } } } @@ -10733,7 +10746,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "0.1.15" + "ret": "~0.1.10" } }, "samsam": { @@ -10749,10 +10762,10 @@ "dev": true, "optional": true, "requires": { - "glob": "7.1.2", - "lodash": "4.17.10", - "scss-tokenizer": "0.2.3", - "yargs": "7.1.0" + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" }, "dependencies": { "camelcase": { @@ -10769,9 +10782,9 @@ "dev": true, "optional": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, "y18n": { @@ -10788,19 +10801,19 @@ "dev": true, "optional": true, "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "y18n": "3.2.1", - "yargs-parser": "5.0.0" + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" } } } @@ -10811,20 +10824,20 @@ "integrity": "sha1-Yw9pwhaqIGuCMvsqqQe98zNrbYM=", "dev": true, "requires": { - "commander": "2.15.1", - "eslint": "2.13.1", + "commander": "^2.8.1", + "eslint": "^2.7.0", "front-matter": "2.1.2", - "fs-extra": "3.0.1", - "glob": "7.1.2", - "globule": "1.2.1", - "gonzales-pe-sl": "4.2.3", - "js-yaml": "3.11.0", - "known-css-properties": "0.3.0", - "lodash.capitalize": "4.2.1", - "lodash.kebabcase": "4.1.1", - "merge": "1.2.0", - "path-is-absolute": "1.0.1", - "util": "0.10.3" + "fs-extra": "^3.0.1", + "glob": "^7.0.0", + "globule": "^1.0.0", + "gonzales-pe-sl": "^4.2.3", + "js-yaml": "^3.5.4", + "known-css-properties": "^0.3.0", + "lodash.capitalize": "^4.1.0", + "lodash.kebabcase": "^4.0.0", + "merge": "^1.2.0", + "path-is-absolute": "^1.0.0", + "util": "^0.10.3" } }, "sass-loader": { @@ -10833,11 +10846,11 @@ "integrity": "sha512-JoiyD00Yo1o61OJsoP2s2kb19L1/Y2p3QFcCdWdF6oomBGKVYuZyqHWemRBfQ2uGYsk+CH3eCguXNfpjzlcpaA==", "dev": true, "requires": { - "clone-deep": "2.0.2", - "loader-utils": "1.1.0", - "lodash.tail": "4.1.1", - "neo-async": "2.5.2", - "pify": "3.0.0" + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0" } }, "saucelabs": { @@ -10846,7 +10859,7 @@ "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", "dev": true, "requires": { - "https-proxy-agent": "2.2.1" + "https-proxy-agent": "^2.2.1" } }, "sax": { @@ -10861,8 +10874,8 @@ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", "dev": true, "requires": { - "ajv": "6.4.0", - "ajv-keywords": "3.2.0" + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" } }, "scss-tokenizer": { @@ -10872,8 +10885,8 @@ "dev": true, "optional": true, "requires": { - "js-base64": "2.4.8", - "source-map": "0.4.4" + "js-base64": "^2.1.8", + "source-map": "^0.4.2" }, "dependencies": { "source-map": { @@ -10883,7 +10896,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -10900,10 +10913,10 @@ "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", "dev": true, "requires": { - "jszip": "3.1.5", - "rimraf": "2.6.2", + "jszip": "^3.1.3", + "rimraf": "^2.5.4", "tmp": "0.0.30", - "xml2js": "0.4.19" + "xml2js": "^0.4.17" }, "dependencies": { "tmp": { @@ -10912,7 +10925,7 @@ "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.1" } } } @@ -10938,7 +10951,7 @@ "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", "dev": true, "requires": { - "semver": "5.5.0" + "semver": "^5.3.0" } }, "semver-greatest-satisfied-range": { @@ -10947,7 +10960,7 @@ "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", "dev": true, "requires": { - "sver-compat": "1.5.0" + "sver-compat": "^1.5.0" } }, "semver-intersect": { @@ -10956,7 +10969,7 @@ "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", "dev": true, "requires": { - "semver": "5.5.0" + "semver": "^5.0.0" } }, "send": { @@ -10966,18 +10979,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.3", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" }, "dependencies": { "mime": { @@ -11000,13 +11013,13 @@ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.4", "batch": "0.6.1", "debug": "2.6.9", - "escape-html": "1.0.3", - "http-errors": "1.6.3", - "mime-types": "2.1.18", - "parseurl": "1.3.2" + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" } }, "serve-static": { @@ -11015,9 +11028,9 @@ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", "send": "0.16.2" } }, @@ -11033,7 +11046,7 @@ "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", "dev": true, "requires": { - "to-object-path": "0.3.0" + "to-object-path": "^0.3.0" } }, "set-immediate-shim": { @@ -11048,10 +11061,10 @@ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -11060,7 +11073,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -11083,8 +11096,8 @@ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "shallow-clone": { @@ -11093,9 +11106,9 @@ "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", "dev": true, "requires": { - "is-extendable": "0.1.1", - "kind-of": "5.1.0", - "mixin-object": "2.0.1" + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" }, "dependencies": { "kind-of": { @@ -11112,7 +11125,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -11135,14 +11148,14 @@ }, "sinon": { "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "resolved": "http://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", "dev": true, "requires": { "formatio": "1.1.1", "lolex": "1.3.2", "samsam": "1.1.2", - "util": "0.10.3" + "util": ">=0.10.3 <1" } }, "slash": { @@ -11169,14 +11182,14 @@ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.6", - "source-map-resolve": "0.5.2", - "use": "3.1.0" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "dependencies": { "define-property": { @@ -11185,7 +11198,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -11194,7 +11207,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -11205,9 +11218,9 @@ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { @@ -11216,7 +11229,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -11225,7 +11238,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -11234,7 +11247,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -11243,9 +11256,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -11256,7 +11269,7 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.2.0" }, "dependencies": { "kind-of": { @@ -11265,7 +11278,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -11276,12 +11289,12 @@ "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { - "debug": "3.1.0", - "engine.io": "3.2.0", - "has-binary2": "1.0.3", - "socket.io-adapter": "1.1.1", + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", "socket.io-client": "2.1.1", - "socket.io-parser": "3.2.0" + "socket.io-parser": "~3.2.0" }, "dependencies": { "debug": { @@ -11311,15 +11324,15 @@ "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "3.1.0", - "engine.io-client": "3.2.1", - "has-binary2": "1.0.3", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "3.2.0", + "socket.io-parser": "~3.2.0", "to-array": "0.1.4" }, "dependencies": { @@ -11341,7 +11354,7 @@ "dev": true, "requires": { "component-emitter": "1.2.1", - "debug": "3.1.0", + "debug": "~3.1.0", "isarray": "2.0.1" }, "dependencies": { @@ -11368,8 +11381,8 @@ "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", "dev": true, "requires": { - "faye-websocket": "0.10.0", - "uuid": "3.2.1" + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" } }, "sockjs-client": { @@ -11378,12 +11391,12 @@ "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=", "dev": true, "requires": { - "debug": "2.6.9", + "debug": "^2.6.6", "eventsource": "0.1.6", - "faye-websocket": "0.11.1", - "inherits": "2.0.3", - "json3": "3.3.2", - "url-parse": "1.4.3" + "faye-websocket": "~0.11.0", + "inherits": "^2.0.1", + "json3": "^3.3.2", + "url-parse": "^1.1.8" }, "dependencies": { "faye-websocket": { @@ -11392,7 +11405,7 @@ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", "dev": true, "requires": { - "websocket-driver": "0.7.0" + "websocket-driver": ">=0.5.1" } } } @@ -11414,8 +11427,8 @@ "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", "dev": true, "requires": { - "async": "2.6.1", - "loader-utils": "1.1.0" + "async": "^2.5.0", + "loader-utils": "^1.1.0" }, "dependencies": { "async": { @@ -11424,7 +11437,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "4.17.10" + "lodash": "^4.17.10" } } } @@ -11435,11 +11448,11 @@ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "atob": "2.1.1", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, "source-map-support": { @@ -11448,8 +11461,8 @@ "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", "dev": true, "requires": { - "buffer-from": "1.1.0", - "source-map": "0.6.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" }, "dependencies": { "source-map": { @@ -11478,8 +11491,8 @@ "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { @@ -11494,8 +11507,8 @@ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { @@ -11510,12 +11523,12 @@ "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", "dev": true, "requires": { - "debug": "2.6.9", - "handle-thing": "1.2.5", - "http-deceiver": "1.2.7", - "safe-buffer": "5.1.2", - "select-hose": "2.0.0", - "spdy-transport": "2.1.0" + "debug": "^2.6.8", + "handle-thing": "^1.2.5", + "http-deceiver": "^1.2.7", + "safe-buffer": "^5.0.1", + "select-hose": "^2.0.0", + "spdy-transport": "^2.0.18" } }, "spdy-transport": { @@ -11524,22 +11537,22 @@ "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", "dev": true, "requires": { - "debug": "2.6.9", - "detect-node": "2.0.3", - "hpack.js": "2.1.6", - "obuf": "1.1.2", - "readable-stream": "2.3.6", - "safe-buffer": "5.1.2", - "wbuf": "1.7.3" + "debug": "^2.6.8", + "detect-node": "^2.0.3", + "hpack.js": "^2.1.6", + "obuf": "^1.1.1", + "readable-stream": "^2.2.9", + "safe-buffer": "^5.0.1", + "wbuf": "^1.7.2" } }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { - "through": "2.3.8" + "through": "2" } }, "split-string": { @@ -11548,7 +11561,7 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "3.0.2" + "extend-shallow": "^3.0.0" } }, "sprintf-js": { @@ -11562,14 +11575,14 @@ "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "dev": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" } }, "ssri": { @@ -11578,7 +11591,7 @@ "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.1.1" } }, "stack-trace": { @@ -11598,7 +11611,7 @@ "integrity": "sha512-9o+nWhiz5wFnrB3hBHs2PTyYrS60M1vvpSzHxwxnIbtY2q9Nt51hZvhrG1+2AxD374ecwyS+IUwfkHRE/2zuGg==", "requires": { "source-map": "0.5.6", - "stackframe": "1.0.4" + "stackframe": "^1.0.4" } }, "static-extend": { @@ -11607,8 +11620,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { "define-property": { @@ -11617,7 +11630,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } @@ -11628,7 +11641,7 @@ "integrity": "sha1-LFlJtTHgf4eojm6k3PrFOqjHWis=", "dev": true, "requires": { - "lodash": "4.17.10" + "lodash": "^4.17.4" } }, "statuses": { @@ -11644,7 +11657,7 @@ "dev": true, "optional": true, "requires": { - "readable-stream": "2.3.6" + "readable-stream": "^2.0.1" } }, "stealthy-require": { @@ -11658,7 +11671,7 @@ "resolved": "https://registry.npmjs.org/stratos-angular6-json-schema-form/-/stratos-angular6-json-schema-form-1.0.3.tgz", "integrity": "sha512-4CZm6hWqIlJQ7T4Bg3SM4YB4F+6KsswmC5Bm6yNMF6OfNPRo7sQuWw5wuAQMw6X3BRUJnxTkJGnG9vH2BpbPPw==", "requires": { - "tslib": "1.9.2" + "tslib": "^1.9.0" } }, "stratos-merge-dirs": { @@ -11667,10 +11680,10 @@ "integrity": "sha512-4StuTlfzL6LXdx+/r0zIm+ayxyPKP0+8338OBn448WursU5njivXu29Av2WXcqmjzcHH48hmmmfHFeBTPsuJCQ==", "dev": true, "requires": { - "inquirer": "0.11.4", - "minimist": "1.2.0", - "node-fs": "0.1.7", - "path": "0.12.7" + "inquirer": "^0.11.0", + "minimist": "^1.2.0", + "node-fs": "~0.1.7", + "path": "^0.12.7" }, "dependencies": { "ansi-styles": { @@ -11685,11 +11698,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "cli-width": { @@ -11704,19 +11717,19 @@ "integrity": "sha1-geM3ToNhvq/y2XAWIG01nQsy+k0=", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "1.1.1", - "figures": "1.7.0", - "lodash": "3.10.1", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^1.0.1", + "figures": "^1.3.5", + "lodash": "^3.3.1", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" } }, "lodash": { @@ -11745,11 +11758,11 @@ "integrity": "sha512-e87eX4LB+KLVOfEF/TeWpNYM9aQFJTO+jsslym7zCZLYd8xlNWZUjmUf00J0DWn7YpoNGdjv0wzkKPcXJ2c5uw==", "dev": true, "requires": { - "circular-json": "0.3.3", - "fs-extra": "3.0.1", - "klaw-sync": "2.1.0", - "mkdirp": "0.3.5", - "underscore": "1.6.0" + "circular-json": "^0.3.1", + "fs-extra": "^3.0.1", + "klaw-sync": "^2.1.0", + "mkdirp": "~0.3.5", + "underscore": "~1.6.0" }, "dependencies": { "circular-json": { @@ -11778,17 +11791,17 @@ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, "stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { - "duplexer": "0.1.1" + "duplexer": "~0.1.1" } }, "stream-each": { @@ -11797,8 +11810,8 @@ "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" } }, "stream-exhaust": { @@ -11813,11 +11826,11 @@ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, "stream-shift": { @@ -11832,10 +11845,10 @@ "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { - "date-format": "1.2.0", - "debug": "3.2.5", - "mkdirp": "0.5.1", - "readable-stream": "2.3.6" + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" }, "dependencies": { "debug": { @@ -11844,7 +11857,7 @@ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "2.1.1" + "ms": "^2.1.1" } }, "ms": { @@ -11861,9 +11874,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -11872,7 +11885,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -11881,7 +11894,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -11890,7 +11903,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "^0.2.0" } }, "strip-eof": { @@ -11905,7 +11918,7 @@ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "4.0.1" + "get-stdin": "^4.0.1" } }, "strip-json-comments": { @@ -11920,8 +11933,8 @@ "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==", "dev": true, "requires": { - "loader-utils": "1.1.0", - "schema-utils": "0.4.7" + "loader-utils": "^1.1.0", + "schema-utils": "^0.4.5" } }, "stylus": { @@ -11930,12 +11943,12 @@ "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", "dev": true, "requires": { - "css-parse": "1.7.0", - "debug": "2.6.9", - "glob": "7.0.6", - "mkdirp": "0.5.1", - "sax": "0.5.8", - "source-map": "0.1.43" + "css-parse": "1.7.x", + "debug": "*", + "glob": "7.0.x", + "mkdirp": "0.5.x", + "sax": "0.5.x", + "source-map": "0.1.x" }, "dependencies": { "glob": { @@ -11944,12 +11957,12 @@ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "source-map": { @@ -11958,7 +11971,7 @@ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -11969,9 +11982,9 @@ "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", "dev": true, "requires": { - "loader-utils": "1.1.0", - "lodash.clonedeep": "4.5.0", - "when": "3.6.4" + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" } }, "supports-color": { @@ -11980,7 +11993,7 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } }, "sver-compat": { @@ -11989,8 +12002,8 @@ "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", "dev": true, "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, "symbol-observable": { @@ -12005,12 +12018,12 @@ "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.10", + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", "slice-ansi": "0.0.4", - "string-width": "2.1.1" + "string-width": "^2.0.0" }, "dependencies": { "ajv": { @@ -12019,8 +12032,8 @@ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, "ajv-keywords": { @@ -12047,11 +12060,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "is-fullwidth-code-point": { @@ -12066,8 +12079,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "dependencies": { "strip-ansi": { @@ -12076,7 +12089,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -12095,7 +12108,7 @@ "integrity": "sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=", "dev": true, "requires": { - "connected-domain": "1.0.0" + "connected-domain": "^1.0.0" } }, "tapable": { @@ -12111,9 +12124,9 @@ "dev": true, "optional": true, "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "temp-fs": { @@ -12122,16 +12135,16 @@ "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", "dev": true, "requires": { - "rimraf": "2.5.4" + "rimraf": "~2.5.2" }, "dependencies": { "rimraf": { "version": "2.5.4", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } } } @@ -12154,8 +12167,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" } }, "through2-filter": { @@ -12164,8 +12177,8 @@ "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", "dev": true, "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" + "through2": "~2.0.0", + "xtend": "~4.0.0" } }, "thunky": { @@ -12186,7 +12199,7 @@ "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "setimmediate": "1.0.5" + "setimmediate": "^1.0.4" } }, "tmp": { @@ -12195,7 +12208,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.2" } }, "to-absolute-glob": { @@ -12204,8 +12217,8 @@ "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", "dev": true, "requires": { - "is-absolute": "1.0.0", - "is-negated-glob": "1.0.0" + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" } }, "to-array": { @@ -12232,7 +12245,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -12241,7 +12254,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -12252,10 +12265,10 @@ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, "to-regex-range": { @@ -12264,8 +12277,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "to-through": { @@ -12274,7 +12287,7 @@ "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", "dev": true, "requires": { - "through2": "2.0.3" + "through2": "^2.0.3" } }, "toposort": { @@ -12289,7 +12302,7 @@ "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" }, "dependencies": { "punycode": { @@ -12325,7 +12338,7 @@ "dev": true, "optional": true, "requires": { - "glob": "6.0.4" + "glob": "^6.0.4" }, "dependencies": { "glob": { @@ -12335,11 +12348,11 @@ "dev": true, "optional": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } @@ -12355,16 +12368,16 @@ "integrity": "sha1-u9KOOK9Kqj6WB2xGbhsiAZfBo84=", "dev": true, "requires": { - "arrify": "1.0.1", - "chalk": "2.2.2", - "diff": "3.5.0", - "make-error": "1.3.4", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18", - "tsconfig": "6.0.0", - "v8flags": "3.1.0", - "yn": "2.0.0" + "arrify": "^1.0.0", + "chalk": "^2.0.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.0", + "tsconfig": "^6.0.0", + "v8flags": "^3.0.0", + "yn": "^2.0.0" }, "dependencies": { "minimist": { @@ -12379,7 +12392,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "0.5.6" + "source-map": "^0.5.6" } } } @@ -12390,8 +12403,8 @@ "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", "dev": true, "requires": { - "strip-bom": "3.0.0", - "strip-json-comments": "2.0.1" + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" }, "dependencies": { "strip-bom": { @@ -12419,18 +12432,18 @@ "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "builtin-modules": "1.1.1", - "chalk": "2.4.1", - "commander": "2.15.1", - "diff": "3.5.0", - "glob": "7.1.2", - "js-yaml": "3.11.0", - "minimatch": "3.0.4", - "resolve": "1.7.1", - "semver": "5.5.0", - "tslib": "1.9.2", - "tsutils": "2.27.1" + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.12.1" }, "dependencies": { "chalk": { @@ -12439,9 +12452,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } } } @@ -12452,7 +12465,7 @@ "integrity": "sha512-AE/7uzp32MmaHvNNFES85hhUDHFdFZp6OAiZcd6y4ZKKIg6orJTm8keYWBhIhrJQH3a4LzNKat7ZPXZt5aTf6w==", "dev": true, "requires": { - "tslib": "1.9.2" + "tslib": "^1.8.1" } }, "tty-browserify": { @@ -12467,7 +12480,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -12483,7 +12496,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-is": { @@ -12493,7 +12506,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.18" } }, "typedarray": { @@ -12514,8 +12527,8 @@ "integrity": "sha512-J0M2i1mQA+ze3EdN9SBi751DNdAXmeFLfJrd/MDIkRc3G3Gbb9OPVSx7GIQvVwfWxQARcYV2DTxIkMyDAk3o9Q==", "dev": true, "requires": { - "commander": "2.16.0", - "source-map": "0.6.1" + "commander": "~2.16.0", + "source-map": "~0.6.1" }, "dependencies": { "commander": { @@ -12545,14 +12558,14 @@ "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", "dev": true, "requires": { - "cacache": "10.0.4", - "find-cache-dir": "1.0.0", - "schema-utils": "0.4.7", - "serialize-javascript": "1.5.0", - "source-map": "0.6.1", - "uglify-es": "3.3.9", - "webpack-sources": "1.1.0", - "worker-farm": "1.6.0" + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "schema-utils": "^0.4.5", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "uglify-es": "^3.3.4", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" }, "dependencies": { "commander": { @@ -12573,8 +12586,8 @@ "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", "dev": true, "requires": { - "commander": "2.13.0", - "source-map": "0.6.1" + "commander": "~2.13.0", + "source-map": "~0.6.1" } } } @@ -12597,15 +12610,15 @@ "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "arr-map": "2.0.2", - "bach": "1.2.0", - "collection-map": "1.0.0", - "es6-weak-map": "2.0.2", - "last-run": "1.1.1", - "object.defaults": "1.1.0", - "object.reduce": "1.0.1", - "undertaker-registry": "1.0.1" + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" } }, "undertaker-registry": { @@ -12620,10 +12633,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" }, "dependencies": { "extend-shallow": { @@ -12632,7 +12645,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "set-value": { @@ -12641,10 +12654,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" } } } @@ -12655,7 +12668,7 @@ "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", "dev": true, "requires": { - "unique-slug": "2.0.0" + "unique-slug": "^2.0.0" } }, "unique-slug": { @@ -12664,7 +12677,7 @@ "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", "dev": true, "requires": { - "imurmurhash": "0.1.4" + "imurmurhash": "^0.1.4" } }, "unique-stream": { @@ -12673,8 +12686,8 @@ "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", "dev": true, "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" } }, "universalify": { @@ -12695,8 +12708,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "dependencies": { "has-value": { @@ -12705,9 +12718,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { "isobject": { @@ -12747,7 +12760,7 @@ "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", "dev": true, "requires": { - "punycode": "2.1.1" + "punycode": "^2.1.0" } }, "urix": { @@ -12786,9 +12799,9 @@ "integrity": "sha512-vugEeXjyYFBCUOpX+ZuaunbK3QXMKaQ3zUnRfIpRBlGkY7QizCnzyyn2ASfcxsvyU3ef+CJppVywnl3Kgf13Gg==", "dev": true, "requires": { - "loader-utils": "1.1.0", - "mime": "2.3.1", - "schema-utils": "1.0.0" + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" }, "dependencies": { "mime": { @@ -12803,9 +12816,9 @@ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "ajv": "6.4.0", - "ajv-errors": "1.0.0", - "ajv-keywords": "3.2.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } @@ -12816,8 +12829,8 @@ "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", "dev": true, "requires": { - "querystringify": "2.0.0", - "requires-port": "1.0.0" + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" } }, "urlgrey": { @@ -12832,7 +12845,7 @@ "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.2" } }, "user-home": { @@ -12841,7 +12854,7 @@ "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" } }, "useragent": { @@ -12850,8 +12863,8 @@ "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, "requires": { - "lru-cache": "2.2.4", - "tmp": "0.0.33" + "lru-cache": "2.2.x", + "tmp": "0.0.x" }, "dependencies": { "lru-cache": { @@ -12891,8 +12904,8 @@ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", "dev": true, "requires": { - "define-properties": "1.1.2", - "object.getownpropertydescriptors": "2.0.3" + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" } }, "utila": { @@ -12919,7 +12932,7 @@ "integrity": "sha512-0m69VIK2dudEf2Ub0xwLQhZkDZu85OmiOpTw+UGDt56ibviYICHziM/3aE+oVg7IjGPp0c83w3eSVqa+lYZ9UQ==", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "^1.0.1" } }, "validate-npm-package-license": { @@ -12928,8 +12941,8 @@ "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, "validate-npm-package-name": { @@ -12938,7 +12951,7 @@ "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", "dev": true, "requires": { - "builtins": "1.0.3" + "builtins": "^1.0.3" } }, "value-or-function": { @@ -12959,9 +12972,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } }, "vinyl": { @@ -12970,12 +12983,12 @@ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.1.2", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } }, "vinyl-fs": { @@ -12984,23 +12997,23 @@ "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", "dev": true, "requires": { - "fs-mkdirp-stream": "1.0.0", - "glob-stream": "6.1.0", - "graceful-fs": "4.1.11", - "is-valid-glob": "1.0.0", - "lazystream": "1.0.0", - "lead": "1.0.0", - "object.assign": "4.1.0", - "pumpify": "1.5.1", - "readable-stream": "2.3.6", - "remove-bom-buffer": "3.0.0", - "remove-bom-stream": "1.2.0", - "resolve-options": "1.1.0", - "through2": "2.0.3", - "to-through": "2.0.0", - "value-or-function": "3.0.0", - "vinyl": "2.1.0", - "vinyl-sourcemap": "1.1.0" + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" }, "dependencies": { "is-valid-glob": { @@ -13017,13 +13030,13 @@ "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", "dev": true, "requires": { - "append-buffer": "1.0.2", - "convert-source-map": "1.5.1", - "graceful-fs": "4.1.11", - "normalize-path": "2.1.1", - "now-and-later": "2.0.0", - "remove-bom-buffer": "3.0.0", - "vinyl": "2.1.0" + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" } }, "vm-browserify": { @@ -13047,9 +13060,9 @@ "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", "dev": true, "requires": { - "chokidar": "2.0.3", - "graceful-fs": "4.1.11", - "neo-async": "2.5.2" + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" } }, "wbuf": { @@ -13058,7 +13071,7 @@ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "requires": { - "minimalistic-assert": "1.0.1" + "minimalistic-assert": "^1.0.0" } }, "web-animations-js": { @@ -13076,7 +13089,7 @@ "@webassemblyjs/validation": "1.4.3", "@webassemblyjs/wasm-parser": "1.4.3", "@webassemblyjs/wast-parser": "1.4.3", - "long": "3.2.0" + "long": "^3.2.0" } }, "webdriver-js-extender": { @@ -13085,8 +13098,8 @@ "integrity": "sha512-fbyKiVu3azzIc5d4+26YfuPQcFTlgFQV5yQ/0OQj4Ybkl4g1YQuIPskf5v5wqwRJhHJnPHthB6tqCjWHOKLWag==", "dev": true, "requires": { - "@types/selenium-webdriver": "3.0.10", - "selenium-webdriver": "3.6.0" + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" } }, "webpack": { @@ -13098,26 +13111,26 @@ "@webassemblyjs/ast": "1.4.3", "@webassemblyjs/wasm-edit": "1.4.3", "@webassemblyjs/wasm-parser": "1.4.3", - "acorn": "5.5.3", - "acorn-dynamic-import": "3.0.0", - "ajv": "6.4.0", - "ajv-keywords": "3.2.0", - "chrome-trace-event": "0.1.3", - "enhanced-resolve": "4.1.0", - "eslint-scope": "3.7.3", - "json-parse-better-errors": "1.0.2", - "loader-runner": "2.3.0", - "loader-utils": "1.1.0", - "memory-fs": "0.4.1", - "micromatch": "3.1.10", - "mkdirp": "0.5.1", - "neo-async": "2.5.2", - "node-libs-browser": "2.1.0", - "schema-utils": "0.4.7", - "tapable": "1.0.0", - "uglifyjs-webpack-plugin": "1.3.0", - "watchpack": "1.6.0", - "webpack-sources": "1.1.0" + "acorn": "^5.0.0", + "acorn-dynamic-import": "^3.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^0.1.1", + "enhanced-resolve": "^4.0.0", + "eslint-scope": "^3.7.1", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^0.4.4", + "tapable": "^1.0.0", + "uglifyjs-webpack-plugin": "^1.2.4", + "watchpack": "^1.5.0", + "webpack-sources": "^1.0.1" } }, "webpack-core": { @@ -13126,8 +13139,8 @@ "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", "dev": true, "requires": { - "source-list-map": "0.1.8", - "source-map": "0.4.4" + "source-list-map": "~0.1.7", + "source-map": "~0.4.1" }, "dependencies": { "source-list-map": { @@ -13142,7 +13155,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -13153,13 +13166,13 @@ "integrity": "sha512-I6Mmy/QjWU/kXwCSFGaiOoL5YEQIVmbb0o45xMoCyQAg/mClqZVTcsX327sPfekDyJWpCxb+04whNyLOIxpJdQ==", "dev": true, "requires": { - "loud-rejection": "1.6.0", - "memory-fs": "0.4.1", - "mime": "2.3.1", - "path-is-absolute": "1.0.1", - "range-parser": "1.2.0", - "url-join": "4.0.0", - "webpack-log": "1.2.0" + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "url-join": "^4.0.0", + "webpack-log": "^1.0.1" }, "dependencies": { "mime": { @@ -13177,32 +13190,32 @@ "dev": true, "requires": { "ansi-html": "0.0.7", - "array-includes": "3.0.3", - "bonjour": "3.5.0", - "chokidar": "2.0.3", - "compression": "1.7.3", - "connect-history-api-fallback": "1.5.0", - "debug": "3.1.0", - "del": "3.0.0", - "express": "4.16.3", - "html-entities": "1.2.1", - "http-proxy-middleware": "0.18.0", - "import-local": "1.0.0", + "array-includes": "^3.0.3", + "bonjour": "^3.5.0", + "chokidar": "^2.0.0", + "compression": "^1.5.2", + "connect-history-api-fallback": "^1.3.0", + "debug": "^3.1.0", + "del": "^3.0.0", + "express": "^4.16.2", + "html-entities": "^1.2.0", + "http-proxy-middleware": "~0.18.0", + "import-local": "^1.0.0", "internal-ip": "1.2.0", - "ip": "1.1.5", - "killable": "1.0.0", - "loglevel": "1.6.1", - "opn": "5.3.0", - "portfinder": "1.0.16", - "selfsigned": "1.10.3", - "serve-index": "1.9.1", + "ip": "^1.1.5", + "killable": "^1.0.0", + "loglevel": "^1.4.1", + "opn": "^5.1.0", + "portfinder": "^1.0.9", + "selfsigned": "^1.9.1", + "serve-index": "^1.7.2", "sockjs": "0.3.19", "sockjs-client": "1.1.5", - "spdy": "3.4.7", - "strip-ansi": "3.0.1", - "supports-color": "5.4.0", + "spdy": "^3.4.1", + "strip-ansi": "^3.0.0", + "supports-color": "^5.1.0", "webpack-dev-middleware": "3.1.3", - "webpack-log": "1.2.0", + "webpack-log": "^1.1.2", "yargs": "11.0.0" }, "dependencies": { @@ -13224,9 +13237,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" }, "dependencies": { "strip-ansi": { @@ -13235,7 +13248,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -13261,9 +13274,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "string-width": { @@ -13272,8 +13285,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "dependencies": { "strip-ansi": { @@ -13282,7 +13295,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } } } @@ -13305,18 +13318,18 @@ "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", "dev": true, "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" } }, "yargs-parser": { @@ -13325,7 +13338,7 @@ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } } } @@ -13336,10 +13349,10 @@ "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", "dev": true, "requires": { - "chalk": "2.2.2", - "log-symbols": "2.2.0", - "loglevelnext": "1.0.5", - "uuid": "3.2.1" + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" } }, "webpack-merge": { @@ -13348,7 +13361,7 @@ "integrity": "sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ==", "dev": true, "requires": { - "lodash": "4.17.10" + "lodash": "^4.17.5" } }, "webpack-sources": { @@ -13357,8 +13370,8 @@ "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", "dev": true, "requires": { - "source-list-map": "2.0.0", - "source-map": "0.6.1" + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" }, "dependencies": { "source-map": { @@ -13375,7 +13388,7 @@ "integrity": "sha1-xcTj1pD50vZKlVDgeodn+Xlqpdg=", "dev": true, "requires": { - "webpack-core": "0.6.9" + "webpack-core": "^0.6.8" } }, "websocket-driver": { @@ -13384,8 +13397,8 @@ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": "0.4.13", - "websocket-extensions": "0.1.3" + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" } }, "websocket-extensions": { @@ -13406,7 +13419,7 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "which-module": { @@ -13421,7 +13434,7 @@ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2 || 2" } }, "window-size": { @@ -13443,7 +13456,7 @@ "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", "dev": true, "requires": { - "errno": "0.1.7" + "errno": "~0.1.7" } }, "wrap-ansi": { @@ -13452,8 +13465,8 @@ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" } }, "wrappy": { @@ -13468,7 +13481,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "ws": { @@ -13477,9 +13490,9 @@ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "async-limiter": "1.0.0", - "safe-buffer": "5.1.2", - "ultron": "1.1.1" + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" } }, "xhr2": { @@ -13493,8 +13506,8 @@ "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", "dev": true, "requires": { - "sax": "1.2.4", - "xmlbuilder": "9.0.7" + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" }, "dependencies": { "sax": { @@ -13534,7 +13547,7 @@ "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", "dev": true, "requires": { - "cuint": "0.2.2" + "cuint": "^0.2.2" } }, "y18n": { @@ -13556,9 +13569,9 @@ "dev": true, "optional": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } }, @@ -13568,7 +13581,7 @@ "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", "dev": true, "requires": { - "camelcase": "3.0.0" + "camelcase": "^3.0.0" }, "dependencies": { "camelcase": { @@ -13585,7 +13598,7 @@ "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", "dev": true, "requires": { - "buffer-crc32": "0.2.13" + "buffer-crc32": "~0.2.3" } }, "yeast": { diff --git a/package.json b/package.json index 704fc1b037..467f635d29 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,8 @@ "@angular/common": "^6.1.1", "@angular/compiler": "^6.1.1", "@angular/core": "^6.1.1", - "@angular/forms": "^6.1.1", "@angular/flex-layout": "^6.0.0-beta.16", + "@angular/forms": "^6.1.1", "@angular/http": "^6.1.1", "@angular/material": "^6.1.0", "@angular/material-moment-adapter": "^6.4.7", @@ -60,7 +60,6 @@ "@ngrx/store-devtools": "^6.0.1", "@swimlane/ngx-charts": "^9.0.0", "angular2-virtual-scroll": "^0.3.1", - "stratos-angular6-json-schema-form": "1.0.3", "core-js": "^2.5.7", "hammerjs": "^2.0.8", "js-yaml": "^3.11.0", @@ -72,6 +71,7 @@ "rxjs": "^6.2.0", "rxjs-spy": "^7.0.2", "rxjs-websockets": "~6.0.0", + "stratos-angular6-json-schema-form": "1.0.3", "ts-md5": "^1.2.4", "web-animations-js": "^2.3.1", "xterm": "^3.5.0", @@ -124,4 +124,4 @@ "tslint": "~5.10.0", "typescript": "~2.9.0" } -} +} \ No newline at end of file diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts index 7184351322..4b1502ed1d 100644 --- a/src/frontend/app/app.module.ts +++ b/src/frontend/app/app.module.ts @@ -1,29 +1,54 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { Params, RouterStateSnapshot } from '@angular/router'; +import { Params, RouterStateSnapshot, RouteReuseStrategy } from '@angular/router'; import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store'; - +import { Store } from '@ngrx/store'; +import { debounceTime, withLatestFrom } from 'rxjs/operators'; import { AppComponent } from './app.component'; import { RouteModule } from './app.routing'; +import { IAppFavMetadata, IOrgFavMetadata, ISpaceFavMetadata } from './cf-favourite-types'; +import { IApp, IOrganization, ISpace } from './core/cf-api.types'; import { CoreModule } from './core/core.module'; +import { CurrentUserPermissions } from './core/current-user-permissions.config'; +import { CurrentUserPermissionsService } from './core/current-user-permissions.service'; import { DynamicExtensionRoutes } from './core/extension/dynamic-extension-routes'; import { ExtensionService } from './core/extension/extension-service'; import { getGitHubAPIURL, GITHUB_API_URL } from './core/github.helpers'; +import { UserFavoriteManager } from './core/user-favorite-manager'; import { CustomImportModule } from './custom-import.module'; import { AboutModule } from './features/about/about.module'; +import { createGetApplicationAction } from './features/applications/application.service'; import { ApplicationsModule } from './features/applications/applications.module'; import { DashboardModule } from './features/dashboard/dashboard.module'; +import { getFullEndpointApiUrl, initEndpointExtensions } from './features/endpoints/endpoint-helpers'; import { HomeModule } from './features/home/home.module'; import { LoginModule } from './features/login/login.module'; import { NoEndpointsNonAdminComponent } from './features/no-endpoints-non-admin/no-endpoints-non-admin.component'; import { ServiceCatalogModule } from './features/service-catalog/service-catalog.module'; import { SetupModule } from './features/setup/setup.module'; import { LoggedInService } from './logged-in.service'; +import { ApplicationStateService } from './shared/components/application-state/application-state.service'; +import { favoritesConfigMapper } from './shared/components/favorites-meta-card/favorite-config-mapper'; import { SharedModule } from './shared/shared.module'; +import { GetAllEndpoints } from './store/actions/endpoint.actions'; +import { GetOrganization } from './store/actions/organization.actions'; +import { RouterNav } from './store/actions/router.actions'; +import { GetSpace } from './store/actions/space.actions'; +import { UpdateUserFavoriteMetadataAction } from './store/actions/user-favourites-actions/update-user-favorite-metadata-action'; +import { AppState } from './store/app-state'; +import { applicationSchemaKey, endpointSchemaKey, organizationSchemaKey, spaceSchemaKey } from './store/helpers/entity-factory'; +import { getAPIRequestDataState } from './store/selectors/api.selectors'; import { AppStoreModule } from './store/store.module'; +import { APIResource } from './store/types/api.types'; +import { EndpointModel } from './store/types/endpoint.types'; +import { IRequestDataState } from './store/types/entity.types'; +import { IEndpointFavMetadata, IFavoriteMetadata, UserFavorite } from './store/types/user-favorites.types'; import { XSRFModule } from './xsrf.module'; -import { initEndpointExtensions } from './features/endpoints/endpoint-helpers'; +import { recentlyVisitedSelector } from './store/selectors/recently-visitied.selectors'; +import { SetRecentlyVisitedEntityAction } from './store/actions/recently-visited.actions'; +import { CustomReuseStrategy } from './route-reuse-stragegy'; + // Create action for router navigation. See // - https://github.com/ngrx/platform/issues/68 @@ -86,14 +111,215 @@ export class CustomRouterStateSerializer ExtensionService, DynamicExtensionRoutes, { provide: GITHUB_API_URL, useFactory: getGitHubAPIURL }, - { provide: RouterStateSerializer, useClass: CustomRouterStateSerializer } // Create action for router navigation + { provide: RouterStateSerializer, useClass: CustomRouterStateSerializer }, // Create action for router navigation + { provide: RouteReuseStrategy, useClass: CustomReuseStrategy } ], bootstrap: [AppComponent] }) export class AppModule { - constructor(private ext: ExtensionService) { + private userFavoriteManager: UserFavoriteManager; + constructor( + ext: ExtensionService, + private permissionService: CurrentUserPermissionsService, + private appStateService: ApplicationStateService, + private store: Store, + ) { ext.init(); // Init Auth Types and Endpoint Types provided by extensions initEndpointExtensions(ext); + // Once the CF modules become an extension point, these should be moved to a CF specific module + this.registerCfFavoriteMappers(); + this.userFavoriteManager = new UserFavoriteManager(store); + const allFavs$ = this.userFavoriteManager.getAllFavorites(); + const recents$ = this.store.select(recentlyVisitedSelector); + const debouncedApiRequestData$ = this.store.select(getAPIRequestDataState).pipe(debounceTime(2000)); + debouncedApiRequestData$.pipe( + withLatestFrom(allFavs$) + ).subscribe( + ([entities, [favoriteGroups, favorites]]) => { + Object.keys(favoriteGroups).forEach(endpointId => { + const favoriteGroup = favoriteGroups[endpointId]; + if (!favoriteGroup.ethereal) { + const endpointFavorite = favorites[endpointId]; + this.syncFavorite(endpointFavorite, entities); + } + favoriteGroup.entitiesIds.forEach(id => { + const favorite = favorites[id]; + this.syncFavorite(favorite, entities); + }); + }); + } + ); + + debouncedApiRequestData$.pipe( + withLatestFrom(recents$) + ).subscribe( + ([entities, recents]) => { + Object.values(recents.entities).forEach(recentEntity => { + const mapper = favoritesConfigMapper.getMapperFunction(recentEntity); + if (entities[recentEntity.entityType] && entities[recentEntity.entityType][recentEntity.entityId]) { + const entity = entities[recentEntity.entityType][recentEntity.entityId]; + const entityToMetadata = favoritesConfigMapper.getEntityMetadata(recentEntity, entity); + const name = mapper(entityToMetadata).name; + if (name && name !== recentEntity.name) { + this.store.dispatch(new SetRecentlyVisitedEntityAction({ + ...recentEntity, + name + })); + } + } + }); + } + ); + } + + private syncFavorite(favorite: UserFavorite, entities: IRequestDataState) { + if (favorite) { + const entity = entities[favorite.entityType][favorite.entityId || favorite.endpointId]; + if (entity) { + const newMetadata = favoritesConfigMapper.getEntityMetadata(favorite, entity); + if (this.metadataHasChanged(favorite.metadata, newMetadata)) { + this.store.dispatch(new UpdateUserFavoriteMetadataAction({ + ...favorite, + metadata: newMetadata + })); + } + } + } + } + + private metadataHasChanged(oldMeta: IFavoriteMetadata, newMeta: IFavoriteMetadata) { + if ((!oldMeta && newMeta) || (oldMeta && !newMeta)) { + return true; + } + const oldKeys = Object.keys(oldMeta); + const newKeys = Object.keys(newMeta); + const oldValues = Object.values(oldMeta); + const newValues = Object.values(newMeta); + if (oldKeys.length !== newKeys.length) { + return true; + } + if (oldKeys.sort().join(',') !== newKeys.sort().join(',')) { + return true; + } + if (oldValues.sort().join(',') !== newValues.sort().join(',')) { + return true; + } + return false; + } + + private registerCfFavoriteMappers() { + const endpointType = 'cf'; + + this.registerCfEndpointMapper(endpointType); + this.registerCfApplicationMapper(endpointType); + this.registerCfSpaceMapper(endpointType); + this.registerCfOrgMapper(endpointType); + } + private registerCfEndpointMapper(endpointType: string) { + favoritesConfigMapper.registerFavoriteConfig({ + endpointType, + entityType: endpointSchemaKey + }, + 'Cloud Foundry', + (endpoint: IEndpointFavMetadata) => ({ + type: endpointType, + routerLink: `/cloud-foundry/${endpoint.guid}`, + lines: [ + ['Address', endpoint.address], + ['User', endpoint.user], + ['Admin', endpoint.admin] + ], + name: endpoint.name, + menuItems: [ + { + label: 'Deploy application', + action: () => this.store.dispatch(new RouterNav({ path: ['applications/deploy'], query: { endpointGuid: endpoint.guid } })), + can: this.permissionService.can(CurrentUserPermissions.APPLICATION_CREATE) + } + ] + }), + () => new GetAllEndpoints(false), + endpoint => ({ + name: endpoint.name, + guid: endpoint.guid, + address: getFullEndpointApiUrl(endpoint), + user: endpoint.user ? endpoint.user.name : undefined, + admin: endpoint.user ? endpoint.user.admin ? 'Yes' : 'No' : undefined + }) + ); + } + + private registerCfApplicationMapper(endpointType: string) { + favoritesConfigMapper.registerFavoriteConfig, IAppFavMetadata>({ + endpointType, + entityType: applicationSchemaKey + }, + 'Application', + (app: IAppFavMetadata) => { + return { + type: applicationSchemaKey, + routerLink: `/applications/${app.cfGuid}/${app.guid}/summary`, + name: app.name + }; + }, + favorite => createGetApplicationAction(favorite.entityId, favorite.endpointId), + app => ({ + guid: app.metadata.guid, + cfGuid: app.entity.cfGuid, + name: app.entity.name, + }) + ); + } + + private registerCfSpaceMapper(endpointType: string) { + favoritesConfigMapper.registerFavoriteConfig, ISpaceFavMetadata>({ + endpointType, + entityType: spaceSchemaKey + }, + 'Space', + (space: ISpaceFavMetadata) => { + return { + type: spaceSchemaKey, + routerLink: `/cloud-foundry/${space.cfGuid}/organizations/${space.orgGuid}/spaces/${space.guid}/summary`, + name: space.name + }; + }, + favorite => new GetSpace(favorite.entityId, favorite.endpointId), + space => ({ + guid: space.metadata.guid, + orgGuid: space.entity.organization_guid ? space.entity.organization_guid : space.entity.organization.metadata.guid, + name: space.entity.name, + cfGuid: space.entity.cfGuid, + }) + ); + + } + private registerCfOrgMapper(endpointType: string) { + + favoritesConfigMapper.registerFavoriteConfig, IOrgFavMetadata>({ + endpointType, + entityType: organizationSchemaKey + }, + 'Organization', + (org: IOrgFavMetadata) => ({ + type: organizationSchemaKey, + routerLink: `/cloud-foundry/${org.cfGuid}/organizations/${org.guid}`, + name: org.name + }), + favorite => new GetOrganization(favorite.entityId, favorite.endpointId), + org => ({ + guid: org.metadata.guid, + status: this.getOrgStatus(org), + name: org.entity.name, + cfGuid: org.entity.cfGuid, + }) + ); + } + private getOrgStatus(org: APIResource) { + if (!org || !org.entity || !org.entity.status) { + return 'Unknown'; + } + return org.entity.status.charAt(0).toUpperCase() + org.entity.status.slice(1); } } diff --git a/src/frontend/app/app.routing.ts b/src/frontend/app/app.routing.ts index 3072bdc2d9..25d9704ae8 100644 --- a/src/frontend/app/app.routing.ts +++ b/src/frontend/app/app.routing.ts @@ -14,11 +14,10 @@ import { UpgradePageComponent } from './features/setup/upgrade-page/upgrade-page import { SharedModule } from './shared/shared.module'; import { PageNotFoundComponentComponent } from './core/page-not-found-component/page-not-found-component.component'; import { DomainMismatchComponent } from './features/setup/domain-mismatch/domain-mismatch.component'; -import { environment } from '../environments/environment'; import { CustomRoutingImportModule } from './custom-import.module'; const appRoutes: Routes = [ - { path: '', redirectTo: 'applications', pathMatch: 'full' }, + { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'uaa', component: ConsoleUaaWizardComponent }, { path: 'upgrade', component: UpgradePageComponent }, { path: 'domainMismatch', component: DomainMismatchComponent }, @@ -29,19 +28,18 @@ const appRoutes: Routes = [ canActivate: [AuthGuardService, EndpointsService], children: [ { - path: 'dashboard', component: HomePageComponent, + path: 'home', component: HomePageComponent, data: { stratosNavigation: { - text: 'Dashboard', - matIcon: 'assessment', - // Experimental - only show in development - hidden: observableOf(environment.production), + text: 'Home', + matIcon: 'home', position: 10 } } }, { - path: 'applications', loadChildren: 'app/features/applications/applications.module#ApplicationsModule', + path: 'applications', + loadChildren: 'app/features/applications/applications.module#ApplicationsModule', data: { stratosNavigation: { text: 'Applications', @@ -120,7 +118,7 @@ const appRoutes: Routes = [ CommonModule, CoreModule, SharedModule, - RouterModule.forRoot(appRoutes), + RouterModule.forRoot(appRoutes, { onSameUrlNavigation: 'reload' }), CustomRoutingImportModule, ] }) diff --git a/src/frontend/app/cf-favourite-types.ts b/src/frontend/app/cf-favourite-types.ts new file mode 100644 index 0000000000..bf5c783bff --- /dev/null +++ b/src/frontend/app/cf-favourite-types.ts @@ -0,0 +1,22 @@ +import { IFavoriteMetadata } from './store/types/user-favorites.types'; + +export interface ISpaceFavMetadata extends IFavoriteMetadata { + guid: string; + orgGuid: string; + name: string; + cfGuid: string; +} + +export interface IOrgFavMetadata extends IFavoriteMetadata { + guid: string; + status: string; + name: string; + cfGuid: string; +} + + +export interface IAppFavMetadata extends IFavoriteMetadata { + guid: string; + cfGuid: string; + name: string; +} diff --git a/src/frontend/app/core/click-stop-propagation.ts b/src/frontend/app/core/click-stop-propagation.directive.ts similarity index 86% rename from src/frontend/app/core/click-stop-propagation.ts rename to src/frontend/app/core/click-stop-propagation.directive.ts index fbf5eac63e..be4a7d705a 100644 --- a/src/frontend/app/core/click-stop-propagation.ts +++ b/src/frontend/app/core/click-stop-propagation.directive.ts @@ -5,7 +5,7 @@ import { Directive, HostListener } from '@angular/core'; }) export class ClickStopPropagationDirective { @HostListener('click', ['$event']) - public onClick(event: any): void { + public onClick(event: any) { event.stopPropagation(); } } diff --git a/src/frontend/app/core/core.module.ts b/src/frontend/app/core/core.module.ts index 981df6f37f..a73689978f 100644 --- a/src/frontend/app/core/core.module.ts +++ b/src/frontend/app/core/core.module.ts @@ -5,7 +5,7 @@ import { RouterModule } from '@angular/router'; import { AuthGuardService } from './auth-guard.service'; import { ButtonBlurOnClickDirective } from './button-blur-on-click.directive'; import { BytesToHumanSize, MegaBytesToHumanSize } from './byte-formatters.pipe'; -import { ClickStopPropagationDirective } from './click-stop-propagation'; +import { ClickStopPropagationDirective } from './click-stop-propagation.directive'; import { CurrentUserPermissionsService } from './current-user-permissions.service'; import { Customizations } from './customizations.types'; import { DotContentComponent } from './dot-content/dot-content.component'; @@ -23,16 +23,22 @@ import { TruncatePipe } from './truncate.pipe'; import { UserService } from './user.service'; import { UtilsService } from './utils.service'; import { WindowRef } from './window-ref/window-ref.service'; +import { EntityFavoriteStarComponent } from './entity-favorite-star/entity-favorite-star.component'; +import { RecentEntitiesComponent } from '../shared/components/recent-entities/recent-entities.component'; +import { MomentModule } from 'ngx-moment'; @NgModule({ imports: [ - MDAppModule + MDAppModule, + RouterModule, + MomentModule ], exports: [ MDAppModule, RouterModule, FormsModule, + MomentModule, ReactiveFormsModule, LogOutDialogComponent, TruncatePipe, @@ -43,7 +49,9 @@ import { WindowRef } from './window-ref/window-ref.service'; ClickStopPropagationDirective, DotContentComponent, ButtonBlurOnClickDirective, - PageNotFoundComponentComponent + PageNotFoundComponentComponent, + EntityFavoriteStarComponent, + RecentEntitiesComponent ], providers: [ AuthGuardService, @@ -68,7 +76,9 @@ import { WindowRef } from './window-ref/window-ref.service'; ClickStopPropagationDirective, DotContentComponent, ButtonBlurOnClickDirective, - PageNotFoundComponentComponent + PageNotFoundComponentComponent, + EntityFavoriteStarComponent, + RecentEntitiesComponent ], entryComponents: [ LogOutDialogComponent diff --git a/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.html b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.html new file mode 100644 index 0000000000..2e0d41e69c --- /dev/null +++ b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.html @@ -0,0 +1,4 @@ +
+ star + star_border +
\ No newline at end of file diff --git a/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.scss b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.scss new file mode 100644 index 0000000000..c8793bce8e --- /dev/null +++ b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.scss @@ -0,0 +1,6 @@ +$size: 24px; +.favorite-star { + cursor: pointer; + height: $size; + width: $size; +} diff --git a/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.spec.ts b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.spec.ts new file mode 100644 index 0000000000..199a101ff9 --- /dev/null +++ b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.spec.ts @@ -0,0 +1,32 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EntityFavoriteStarComponent } from './entity-favorite-star.component'; +import { BaseTestModulesNoShared } from '../../test-framework/cloud-foundry-endpoint-service.helper'; +import { ConfirmationDialogService } from '../../shared/components/confirmation-dialog.service'; + +describe('EntityFavoriteStarComponent', () => { + let component: EntityFavoriteStarComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + providers: [ + ConfirmationDialogService + ], + declarations: [ + ], + imports: [...BaseTestModulesNoShared], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EntityFavoriteStarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.ts b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.ts new file mode 100644 index 0000000000..f47ec8263e --- /dev/null +++ b/src/frontend/app/core/entity-favorite-star/entity-favorite-star.component.ts @@ -0,0 +1,65 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; + +import { AppState } from '../../store/app-state'; +import { UserFavorite, IFavoriteMetadata } from '../../store/types/user-favorites.types'; +import { UserFavoriteManager } from '../user-favorite-manager'; +import { ConfirmationDialogService } from '../../shared/components/confirmation-dialog.service'; +import { tap, first } from 'rxjs/operators'; +import { ConfirmationDialogConfig } from '../../shared/components/confirmation-dialog.config'; +import { favoritesConfigMapper } from '../../shared/components/favorites-meta-card/favorite-config-mapper'; + +@Component({ + selector: 'app-entity-favorite-star', + templateUrl: './entity-favorite-star.component.html', + styleUrls: ['./entity-favorite-star.component.scss'] +}) +export class EntityFavoriteStarComponent { + + @Input() + set favorite(favorite: UserFavorite) { + const name = favoritesConfigMapper.getPrettyTypeName(favorite); + this.confirmationDialogConfig.message = + `Are you sure you would you like to unfavorite this ${name ? name.toLocaleLowerCase() : 'favorite'}?`; + this.isFavorite$ = this.userFavoriteManager.getIsFavoriteObservable(favorite); + this._favorite = favorite; + } + private _favorite: UserFavorite; + + @Input() + private confirmRemoval = false; + + private userFavoriteManager: UserFavoriteManager; + + public isFavorite$: Observable; + + private confirmationDialogConfig = new ConfirmationDialogConfig('Unfavorite?', '', 'Yes', true); + + constructor(store: Store, private confirmDialog: ConfirmationDialogService) { + this.userFavoriteManager = new UserFavoriteManager(store); + } + + public toggleFavorite(event: Event) { + event.cancelBubble = true; + event.stopPropagation(); + if (this.confirmRemoval) { + this.isFavorite$.pipe( + first(), + tap(is => { + if (is) { + this.confirmDialog.open(this.confirmationDialogConfig, this._toggleFavorite); + } else { + this._toggleFavorite(); + } + }) + ).subscribe(); + } else { + this._toggleFavorite(); + } + } + + private _toggleFavorite = () => { + this.userFavoriteManager.toggleFavorite(this._favorite); + } +} diff --git a/src/frontend/app/core/jetstream.helpers.ts b/src/frontend/app/core/jetstream.helpers.ts index a5ce0d94ba..ba7ffb3082 100644 --- a/src/frontend/app/core/jetstream.helpers.ts +++ b/src/frontend/app/core/jetstream.helpers.ts @@ -6,7 +6,7 @@ export interface JetStreamError { errorResponse: any; } -export function isJetStreamError(obj): JetStreamError { +export function isJetStreamError(obj: Partial): JetStreamError { return obj && obj.error && obj.error.status && obj.error.statusCode && 'errorResponse' in obj ? diff --git a/src/frontend/app/core/user-favorite-helpers.ts b/src/frontend/app/core/user-favorite-helpers.ts new file mode 100644 index 0000000000..bd919f27fa --- /dev/null +++ b/src/frontend/app/core/user-favorite-helpers.ts @@ -0,0 +1,54 @@ +import { EndpointModel } from '../store/types/endpoint.types'; +import { IFavoriteMetadata, UserFavorite, UserFavoriteEndpoint } from '../store/types/user-favorites.types'; +import { CfAPIResource } from './../store/types/api.types'; + +export function isEndpointTypeFavorite(favorite: UserFavorite) { + return !favorite.entityId; +} + + +export function getFavoriteFromCfEntity(entity, entityKey: string) { + if (isCfEntity(entity as CfAPIResource)) { + return new UserFavorite( + entity.entity.cfGuid, + 'cf', + entityKey, + entity.metadata.guid, + entity + ); + } + return null; +} + +export function getFavoriteFromEndpointEntity(endpoint: EndpointModel) { + if (isEndpointEntity(endpoint)) { + return new UserFavoriteEndpoint( + endpoint.guid, + endpoint.cnsi_type, + endpoint + ); + } + return null; +} + +export function deriveEndpointFavoriteFromFavorite(favorite: UserFavorite) { + if (favorite.entityType !== 'endpoint') { + const endpointFav = { + ...favorite + }; + endpointFav.entityId = null; + endpointFav.entityType = 'endpoint'; + endpointFav.guid = UserFavorite.buildFavoriteStoreEntityGuid(endpointFav); + return endpointFav; + } + return favorite; +} + +function isEndpointEntity(endpoint: EndpointModel) { + return endpoint && endpoint.guid && endpoint.cnsi_type; +} + +function isCfEntity(entity: CfAPIResource) { + return entity && entity.entity.cfGuid && entity.metadata && entity.metadata.guid; +} + diff --git a/src/frontend/app/core/user-favorite-manager.ts b/src/frontend/app/core/user-favorite-manager.ts new file mode 100644 index 0000000000..a9f4518d22 --- /dev/null +++ b/src/frontend/app/core/user-favorite-manager.ts @@ -0,0 +1,159 @@ +import { Store } from '@ngrx/store'; +import { combineLatest, Observable, of } from 'rxjs'; +import { filter, map, switchMap, tap } from 'rxjs/operators'; +import { favoritesConfigMapper, TFavoriteMapperFunction } from '../shared/components/favorites-meta-card/favorite-config-mapper'; +import { ToggleUserFavoriteAction } from '../store/actions/user-favourites-actions/toggle-user-favorite-action'; +import { AppState, IRequestEntityTypeState } from '../store/app-state'; +import { + errorFetchingFavoritesSelector, + favoriteEntitiesSelector, + favoriteGroupsSelector, + fetchingFavoritesSelector +} from '../store/selectors/favorite-groups.selectors'; +import { isFavorite } from '../store/selectors/favorite.selectors'; +import { IUserFavoritesGroups } from '../store/types/favorite-groups.types'; +import { IFavoriteMetadata, UserFavorite, UserFavoriteEndpoint } from '../store/types/user-favorites.types'; +import { IEndpointFavMetadata } from './../store/types/user-favorites.types'; +import { endpointEntitiesSelector } from '../store/selectors/endpoint.selectors'; + +export interface IFavoriteEntity { + type: string; + prettyName: string; + cardMapper: TFavoriteMapperFunction; + favorite: UserFavorite; +} + +export interface IGroupedFavorites { + endpoint: IHydrationResults; + entities: IHydrationResults[]; +} + + +export interface IAllFavorites { + fetching: boolean; + error: boolean; + entityGroups: IGroupedFavorites[]; +} + +export interface IHydrationResults { + type: string; + cardMapper: TFavoriteMapperFunction; + prettyName: string; + favorite: UserFavorite; +} + +export class UserFavoriteManager { + constructor(private store: Store) { } + + private getTypeAndID(favorite: UserFavorite) { + const type = favorite.entityType; + return { + type, + id: favorite.entityId || favorite.endpointId + }; + } + + public getAllFavorites() { + const waitForFavorites$ = this.getWaitForFavoritesObservable(); + const favoriteGroups$ = this.store.select(favoriteGroupsSelector); + const favoriteEntities$ = this.store.select(favoriteEntitiesSelector); + const combined$ = combineLatest( + favoriteGroups$, + favoriteEntities$ + ); + return waitForFavorites$ + .pipe(switchMap(() => combined$)); + } + + private getWaitForFavoritesObservable() { + return combineLatest( + this.store.select(fetchingFavoritesSelector), + this.store.select(errorFetchingFavoritesSelector) + ).pipe( + tap(([fetching, error]) => { + if (error) { + throw new Error('Could not fetch favorites'); + } + }), + filter(([fetching]) => fetching === false), + ); + } + + public hydrateAllFavorites(): Observable { + return this.getHydrateObservable(); + } + + private getHydrateObservable() { + return this.getAllFavorites().pipe( + switchMap(([groups, favoriteEntities]) => this.getHydratedGroups(groups, favoriteEntities)) + ); + } + + private getHydratedGroups = ( + groups: IUserFavoritesGroups, + favoriteEntities: IRequestEntityTypeState> + ): Observable => { + const hydrationResults$ = Object.keys(groups).map( + endpointGuid => this.hydrateGroup(groups[endpointGuid].entitiesIds, endpointGuid, favoriteEntities) + ); + if (!hydrationResults$ || !hydrationResults$.length) { + return of([]); + } + return combineLatest( + hydrationResults$ + ); + } + + private hydrateGroup( + favEntitiesGuid: string[], + endpointFavoriteGuid: string, + favoriteEntities: IRequestEntityTypeState> + ): Observable { + const endpointFav = favoriteEntities[endpointFavoriteGuid] as UserFavorite; + const entities = favEntitiesGuid.map(guid => this.mapToHydrated(favoriteEntities[guid])); + if (!endpointFav) { + return this.store.select(endpointEntitiesSelector).pipe( + map(endpoints => { + const endpointGuid = UserFavorite.getEntityGuidFromFavoriteGuid(endpointFavoriteGuid); + const endpointEntity = endpoints[endpointGuid]; + return new UserFavoriteEndpoint( + endpointGuid, + endpointEntity.cnsi_type, + endpointEntity + ); + }), + map(endpointFavorite => ({ + endpoint: this.mapToHydrated(endpointFavorite), + entities + })) + ); + } + return of({ + endpoint: this.mapToHydrated(endpointFav), + entities + }); + } + + private mapToHydrated = (favorite: UserFavorite): IHydrationResults => { + return { + type: this.getTypeAndID(favorite).type, + cardMapper: favoritesConfigMapper.getMapperFunction(favorite), + prettyName: favoritesConfigMapper.getPrettyTypeName(favorite), + favorite + }; + } + + public hydrateFavorite(favorite: UserFavorite): IFavoriteMetadata { + return favorite.metadata; + } + + public getIsFavoriteObservable(favorite: UserFavorite) { + return this.store.select( + isFavorite(favorite) + ); + } + + public toggleFavorite(favorite: UserFavorite) { + this.store.dispatch(new ToggleUserFavoriteAction(favorite)); + } +} diff --git a/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.html b/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.html index 20a207554e..c8b174e511 100644 --- a/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.html +++ b/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.html @@ -1,4 +1,4 @@ - +

{{ (applicationService.application$ | async)?.app?.entity?.name }}

; + + public favorite$ = this.applicationService.app$.pipe( + filter(app => !!app), + map(app => new UserFavorite>( + this.applicationService.cfGuid, + 'cf', + applicationSchemaKey, + this.applicationService.appGuid, + app.entity + )) + ); + + isBusyUpdating$: Observable<{ updating: boolean }>; public extensionActions: StratosActionMetadata[] = getActionsFromExtensions(StratosActionType.Application); diff --git a/src/frontend/app/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.html b/src/frontend/app/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.html index 93faee9b91..880c7c1edc 100644 --- a/src/frontend/app/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.html +++ b/src/frontend/app/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.html @@ -1,4 +1,4 @@ - +

{{ (cfEndpointService.endpoint$ | async)?.entity.name }}

- -
- + \ No newline at end of file diff --git a/src/frontend/app/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts b/src/frontend/app/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts index 40aaf55492..6d1c33c7e6 100644 --- a/src/frontend/app/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts +++ b/src/frontend/app/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts @@ -12,6 +12,7 @@ import { StratosActionType, StratosTabType, } from '../../../../../../core/extension/extension-service'; +import { getFavoriteFromCfEntity } from '../../../../../../core/user-favorite-helpers'; import { ConfirmationDialogConfig } from '../../../../../../shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../../../shared/components/confirmation-dialog.service'; import { IHeaderBreadcrumb } from '../../../../../../shared/components/page-header/page-header.types'; @@ -19,10 +20,12 @@ import { CfUserService } from '../../../../../../shared/data-services/cf-user.se import { RouterNav } from '../../../../../../store/actions/router.actions'; import { AppState } from '../../../../../../store/app-state'; import { entityFactory, spaceSchemaKey } from '../../../../../../store/helpers/entity-factory'; +import { UserFavorite } from '../../../../../../store/types/user-favorites.types'; import { getActiveRouteCfOrgSpaceProvider } from '../../../../cf.helpers'; import { CloudFoundryEndpointService } from '../../../../services/cloud-foundry-endpoint.service'; import { CloudFoundryOrganizationService } from '../../../../services/cloud-foundry-organization.service'; import { CloudFoundrySpaceService } from '../../../../services/cloud-foundry-space.service'; +import { ISpaceFavMetadata } from '../../../../../../cf-favourite-types'; @Component({ selector: 'app-cloud-foundry-space-base', @@ -77,6 +80,7 @@ export class CloudFoundrySpaceBaseComponent implements OnDestroy { private deleteRedirectSub: Subscription; public extensionActions: StratosActionMetadata[] = getActionsFromExtensions(StratosActionType.CloudFoundryOrg); + public favorite$: Observable>; constructor( public cfEndpointService: CloudFoundryEndpointService, @@ -85,6 +89,9 @@ export class CloudFoundrySpaceBaseComponent implements OnDestroy { private store: Store, private confirmDialog: ConfirmationDialogService ) { + this.favorite$ = cfSpaceService.space$.pipe( + map(space => getFavoriteFromCfEntity(space.entity, spaceSchemaKey)) + ); this.isFetching$ = cfSpaceService.space$.pipe( map(space => space.entityRequestInfo.fetching) ); diff --git a/src/frontend/app/features/dashboard/dashboard-base/dashboard-base.component.ts b/src/frontend/app/features/dashboard/dashboard-base/dashboard-base.component.ts index a06920ba0b..3bdd0a8a32 100644 --- a/src/frontend/app/features/dashboard/dashboard-base/dashboard-base.component.ts +++ b/src/frontend/app/features/dashboard/dashboard-base/dashboard-base.component.ts @@ -5,18 +5,17 @@ import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Route, Router } import { Store } from '@ngrx/store'; import { Subscription } from 'rxjs'; import { debounceTime, filter, withLatestFrom } from 'rxjs/operators'; - +import { EndpointHealthCheck } from '../../../core/endpoints-health-checks'; import { EndpointsService } from '../../../core/endpoints.service'; +import { GetCFInfo } from '../../../store/actions/cloud-foundry.actions'; import { GetCurrentUsersRelations } from '../../../store/actions/permissions.actions'; +import { GetUserFavoritesAction } from '../../../store/actions/user-favourites-actions/get-user-favorites-action'; import { AppState } from '../../../store/app-state'; -import { MetricsService } from '../../metrics/services/metrics-service'; -import { EventWatcherService } from './../../../core/event-watcher/event-watcher.service'; import { PageHeaderService } from './../../../core/page-header-service/page-header.service'; import { ChangeSideNavMode, CloseSideNav, OpenSideNav } from './../../../store/actions/dashboard-actions'; import { DashboardState } from './../../../store/reducers/dashboard-reducer'; import { SideNavItem } from './../side-nav/side-nav.component'; -import { EndpointHealthCheck } from '../../../core/endpoints-health-checks'; -import { GetCFInfo } from '../../../store/actions/cloud-foundry.actions'; + @Component({ @@ -30,11 +29,9 @@ export class DashboardBaseComponent implements OnInit, OnDestroy, AfterContentIn constructor( public pageHeaderService: PageHeaderService, private store: Store, - private eventWatcherService: EventWatcherService, private breakpointObserver: BreakpointObserver, private router: Router, private activatedRoute: ActivatedRoute, - private metricsService: MetricsService, private endpointsService: EndpointsService, ) { if (this.breakpointObserver.isMatched(Breakpoints.Handset)) { @@ -64,6 +61,7 @@ export class DashboardBaseComponent implements OnInit, OnDestroy, AfterContentIn new EndpointHealthCheck('cf', (endpoint) => this.store.dispatch(new GetCFInfo(endpoint.guid))) ); this.dispatchRelations(); + this.store.dispatch(new GetUserFavoritesAction()); const dashboardState$ = this.store.select('dashboard'); this.fullView = this.isFullView(this.activatedRoute.snapshot); this.routeChangeSubscription = this.router.events.pipe( diff --git a/src/frontend/app/features/home/home/home-page.component.html b/src/frontend/app/features/home/home/home-page.component.html index 96acc6b904..567b346002 100644 --- a/src/frontend/app/features/home/home/home-page.component.html +++ b/src/frontend/app/features/home/home/home-page.component.html @@ -1,3 +1,16 @@ - -

Dashboard

-
\ No newline at end of file + +

Home

+
+
+
+

Favorites

+ +
+
+

Session

+ +
+
+ + + \ No newline at end of file diff --git a/src/frontend/app/features/home/home/home-page.component.scss b/src/frontend/app/features/home/home/home-page.component.scss index e69de29bb2..e73df1b4da 100644 --- a/src/frontend/app/features/home/home/home-page.component.scss +++ b/src/frontend/app/features/home/home/home-page.component.scss @@ -0,0 +1,28 @@ +@import '../../../../sass/mixins'; + +.favorites-list { + flex: 2; + @include breakpoint(tablet) { + margin-right: 40px; + } +} +.recent-list { + flex: 1; +} +.stats-panel { + flex: 40%; + margin-left: 20px; + padding-left: 24px; +} + +.home-page { + display: flex; + flex-direction: column; + &__header { + margin-top: 0; + } + + @include breakpoint(tablet) { + flex-direction: row; + } +} diff --git a/src/frontend/app/features/home/home/home-page.component.ts b/src/frontend/app/features/home/home/home-page.component.ts index 228ab7af34..f6321e78a4 100644 --- a/src/frontend/app/features/home/home/home-page.component.ts +++ b/src/frontend/app/features/home/home/home-page.component.ts @@ -1,4 +1,9 @@ import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { EndpointsService } from '../../../core/endpoints.service'; +import { AppState } from '../../../store/app-state'; @Component({ selector: 'app-home-page', @@ -6,7 +11,14 @@ import { Component } from '@angular/core'; styleUrls: ['./home-page.component.scss'] }) export class HomePageComponent { + public allEndpointIds$: Observable; + public haveRegistered$: Observable; - constructor() { + constructor(endpointsService: EndpointsService, store: Store) { + this.allEndpointIds$ = endpointsService.endpoints$.pipe( + map(endpoints => Object.values(endpoints).map(endpoint => endpoint.guid)) + ); + this.haveRegistered$ = endpointsService.haveRegistered$; } } + diff --git a/src/frontend/app/features/metrics/services/metrics-service.ts b/src/frontend/app/features/metrics/services/metrics-service.ts index 4228150c16..dc9fc388c0 100644 --- a/src/frontend/app/features/metrics/services/metrics-service.ts +++ b/src/frontend/app/features/metrics/services/metrics-service.ts @@ -2,12 +2,11 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map, publishReplay, refCount } from 'rxjs/operators'; -import { CloudFoundryService } from '../../../shared/data-services/cloud-foundry.service'; import { PaginationMonitor } from '../../../shared/monitors/pagination-monitor'; import { PaginationMonitorFactory } from '../../../shared/monitors/pagination-monitor.factory'; import { endpointSchemaKey, entityFactory } from '../../../store/helpers/entity-factory'; import { APIResource, EntityInfo } from '../../../store/types/api.types'; -import { EndpointModel } from '../../../store/types/endpoint.types'; +import { EndpointModel, endpointListKey } from '../../../store/types/endpoint.types'; import { getFullEndpointApiUrl } from '../../endpoints/endpoint-helpers'; export interface MetricsEndpointProvider { @@ -27,7 +26,7 @@ export class MetricsService { private paginationMonitorFactory: PaginationMonitorFactory ) { this.endpointsMonitor = this.paginationMonitorFactory.create( - CloudFoundryService.EndpointList, + endpointListKey, entityFactory(endpointSchemaKey) ); diff --git a/src/frontend/app/route-reuse-stragegy.ts b/src/frontend/app/route-reuse-stragegy.ts new file mode 100644 index 0000000000..59bac6f876 --- /dev/null +++ b/src/frontend/app/route-reuse-stragegy.ts @@ -0,0 +1,17 @@ +import { AppComponent } from './app.component'; +import { ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle } from '@angular/router'; +import { DashboardBaseComponent } from './features/dashboard/dashboard-base/dashboard-base.component'; + + +export class CustomReuseStrategy extends RouteReuseStrategy { + shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; } + store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void { } + shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; } + retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null; } + + shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { + const isDashboard = curr.component === DashboardBaseComponent && future.component === DashboardBaseComponent; + const isAppComp = curr.component === AppComponent && future.component === AppComponent; + return isDashboard || isAppComp; + } +} diff --git a/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.spec.ts b/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.spec.ts index d5d12fd1d6..f7ce470c7a 100644 --- a/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.spec.ts +++ b/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.spec.ts @@ -1,6 +1,7 @@ import { CommonModule } from '@angular/common'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ActivatedRoute } from '@angular/router'; import { StoreModule } from '@ngrx/store'; import { CoreModule } from '../../../../core/core.module'; @@ -31,7 +32,16 @@ describe('CreateApplicationStep1Component', () => { } ) ], - providers: [CfOrgSpaceDataService, PaginationMonitorFactory] + providers: [CfOrgSpaceDataService, PaginationMonitorFactory, { + provide: ActivatedRoute, + useValue: { + root: { + snapshot: { + queryParams: { endpointGuid: null }, + } + } + } + }] }) .compileComponents(); })); diff --git a/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.ts b/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.ts index a0f5901184..bc8d24c275 100644 --- a/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.ts +++ b/src/frontend/app/shared/components/create-application/create-application-step1/create-application-step1.component.ts @@ -1,5 +1,6 @@ import { AfterContentInit, Component, Input, OnInit, ViewChild } from '@angular/core'; import { NgForm } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; import { asapScheduler, Observable, of as observableOf } from 'rxjs'; import { map, observeOn, startWith, switchMap, withLatestFrom } from 'rxjs/operators'; @@ -25,7 +26,8 @@ export class CreateApplicationStep1Component implements OnInit, AfterContentInit isMarketplaceMode: boolean; constructor( private store: Store, - public cfOrgSpaceService: CfOrgSpaceDataService + public cfOrgSpaceService: CfOrgSpaceDataService, + public route: ActivatedRoute ) { } public spaces$: Observable; @@ -52,6 +54,9 @@ export class CreateApplicationStep1Component implements OnInit, AfterContentInit } ngOnInit() { + if (this.route.root.snapshot.queryParams.endpointGuid) { + this.cfOrgSpaceService.cf.select.next(this.route.root.snapshot.queryParams.endpointGuid); + } this.spaces$ = this.getSpacesFromPermissions(); this.hasOrgs$ = this.cfOrgSpaceService.org.list$.pipe( map(o => o && o.length > 0) diff --git a/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.html b/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.html index f8f6c8f7a0..057ce86b12 100644 --- a/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.html +++ b/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.html @@ -1,2 +1,3 @@ - - + + \ No newline at end of file diff --git a/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.ts b/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.ts index 22f4200bdf..7c7d12f857 100644 --- a/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.ts +++ b/src/frontend/app/shared/components/endpoints-missing/endpoints-missing.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, Input, OnDestroy } from '@angular/core'; +import { AfterViewInit, Component, Input, OnDestroy, OnInit } from '@angular/core'; import { MatSnackBar, MatSnackBarRef, SimpleSnackBar } from '@angular/material'; import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { delay, map, startWith, tap } from 'rxjs/operators'; @@ -11,7 +11,9 @@ import { EndpointsService } from '../../../core/endpoints.service'; templateUrl: './endpoints-missing.component.html', styleUrls: ['./endpoints-missing.component.scss'] }) -export class EndpointsMissingComponent implements AfterViewInit, OnDestroy { +export class EndpointsMissingComponent implements AfterViewInit, OnDestroy, OnInit { + + @Input() showToolbarHint = true; noContent$: Observable<{ firstLine: string; secondLine: { text: string; }; }>; snackBarText = { @@ -21,9 +23,7 @@ export class EndpointsMissingComponent implements AfterViewInit, OnDestroy { noneRegisteredText = { firstLine: 'There are no registered endpoints', - toolbarLink: { - text: 'Register an endpoint' - }, + toolbarLink: null, secondLine: { text: 'Use the Endpoints view to register' }, @@ -39,7 +39,13 @@ export class EndpointsMissingComponent implements AfterViewInit, OnDestroy { private _snackBar: MatSnackBarRef; constructor(private snackBar: MatSnackBar, public endpointsService: EndpointsService) { } - + ngOnInit() { + if (this.showToolbarHint) { + this.noneRegisteredText.toolbarLink = { + text: 'Register an endpoint' + }; + } + } ngAfterViewInit() { this.noContent$ = observableCombineLatest( this.endpointsService.haveRegistered$, diff --git a/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.html b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.html new file mode 100644 index 0000000000..10c5b5e7e6 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.html @@ -0,0 +1,37 @@ +
+
+ + + + + + + + + {{favoriteType.prettyName}} + + + +
+
No favorites found for the current filters.
+
+ +
+ + + + +
+ +
+
+ + + +
+
\ No newline at end of file diff --git a/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.scss b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.scss new file mode 100644 index 0000000000..fdacf916d4 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.scss @@ -0,0 +1,38 @@ +@import '../../../../sass/mixins'; + +.favorite-entity-list { + $bottom-space: 30px; + display: flex; + flex-direction: column; + &__search-form { + padding-left: 5px; + padding-top: 1.25em; + } + &__name-search { + padding-right: 20px; + } + &__cards { + display: grid; + grid-column-gap: 10px; + grid-row-gap: 10px; + grid-template-columns: 1fr; + min-height: 0; + min-width: 0; + @include breakpoint(tablet) { + grid-column-gap: $bottom-space; + grid-row-gap: $bottom-space; + grid-template-columns: repeat(3, 1fr); + } + } + &__card { + min-width: 0; + } + &__expand-button { + height: $bottom-space; + line-height: $bottom-space; + margin: auto; + margin-bottom: -20px; + margin-top: 10px; + width: $bottom-space; + } +} diff --git a/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.spec.ts b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.spec.ts new file mode 100644 index 0000000000..20af4d575d --- /dev/null +++ b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.spec.ts @@ -0,0 +1,30 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FavoritesEntityListComponent } from './favorites-entity-list.component'; +import { BaseTestModulesNoShared } from '../../../test-framework/cloud-foundry-endpoint-service.helper'; +import { SharedModule } from '../../shared.module'; + +describe('FavoritesEntityListComponent', () => { + let component: FavoritesEntityListComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + ...BaseTestModulesNoShared, + SharedModule + ], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FavoritesEntityListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.ts b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.ts new file mode 100644 index 0000000000..3867c8f499 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-entity-list/favorites-entity-list.component.ts @@ -0,0 +1,135 @@ +import { AfterViewInit, Component, EventEmitter, Input, ViewChild } from '@angular/core'; +import { NgModel } from '@angular/forms'; +import { combineLatest, Observable, ReplaySubject } from 'rxjs'; +import { map, startWith, tap, scan } from 'rxjs/operators'; +import { IFavoriteEntity } from '../../../core/user-favorite-manager'; +import { favoritesConfigMapper, IFavoriteTypes } from '../favorites-meta-card/favorite-config-mapper'; + +@Component({ + selector: 'app-favorites-entity-list', + templateUrl: './favorites-entity-list.component.html', + styleUrls: ['./favorites-entity-list.component.scss'] +}) +export class FavoritesEntityListComponent implements AfterViewInit { + + @Input() + set entities(favoriteEntities: IFavoriteEntity[]) { + this._entities = favoriteEntities ? [...favoriteEntities] : favoriteEntities; + this.entitiesSubject.next(favoriteEntities); + this.hasEntities = this._entities && this._entities.length > 0; + } + @Input() + public placeholder = false; + + @Input() + public endpointDisconnected = false; + + @Input() + set endpointTypes(types: string[] | string) { + if (!this.favoriteTypes) { + if (Array.isArray(types)) { + this.favoriteTypes = types.reduce((allTypes, endpointType) => { + return [ + ...allTypes, + ...favoritesConfigMapper.getAllTypesForEndpoint(endpointType) + ]; + }, []); + } else { + this.favoriteTypes = favoritesConfigMapper.getAllTypesForEndpoint(types) || []; + } + } + } + + @ViewChild('nameChange') public nameChange: NgModel; + + public hasEntities = false; + public typeSubject = new ReplaySubject(); + private entitiesSubject = new ReplaySubject(); + private limitToggleSubject = new ReplaySubject(); + + private entities$ = this.entitiesSubject.asObservable(); + public limitedEntities$: Observable; + public searchedEntities$: Observable; + + public noResultsDueToFilter$: Observable; + + public favoriteTypes: IFavoriteTypes[] = null; + + // User to filter favorites + public filterName: string; + public filterType: string; + + public _entities: IFavoriteEntity[] = []; + + public limitedEntities: IFavoriteEntity[]; + public minLimit = 3; + public limit = this.minLimit; + + public limitToggle$ = this.limitToggleSubject.asObservable().pipe( + scan((acc) => this.minLimit === acc ? null : this.minLimit, this.minLimit), + startWith(this.minLimit) + ); + + public toggleExpand() { + this.limitToggleSubject.next(this.minLimit ? null : this.minLimit); + } + + public typeChanged(type: string) { + this.typeSubject.next(type); + } + + private limitEntities(entities: IFavoriteEntity[], limit: number) { + if (!entities || limit === null) { + return entities; + } else { + return entities.splice(0, limit); + } + } + + public trackByFavoriteId(index: number, entity: IFavoriteEntity) { + return entity.favorite.guid; + } + + ngAfterViewInit() { + const type$ = this.typeSubject.asObservable().pipe(startWith(null)); + const typesEntities$ = combineLatest( + this.entities$, + type$ + ).pipe( + map(([entities, type]) => { + if (!type) { + return entities; + } + return entities.filter(entity => entity.favorite.entityType === type); + }) + ); + this.searchedEntities$ = combineLatest( + typesEntities$, + this.nameChange.valueChanges, + ).pipe( + map(([entities, nameSearch]) => { + if (!nameSearch) { + return entities; + } + const searchableEntities = [...entities]; + return searchableEntities.filter(entity => entity.cardMapper(entity.favorite.metadata).name.search(nameSearch) !== -1); + }), + map(searchEntities => searchEntities || []) + ); + this.limitedEntities$ = combineLatest( + this.searchedEntities$, + this.limitToggle$ + ).pipe( + map(([entities, limit]) => this.limitEntities([...entities], limit)), + map(limitedEntities => limitedEntities || []) + ); + + this.noResultsDueToFilter$ = combineLatest( + this.nameChange.valueChanges, + type$, + this.limitedEntities$, + ).pipe( + map(([nameSearch, type, entities]) => entities.length === 0 && (nameSearch || type)) + ); + } +} diff --git a/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.html b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.html new file mode 100644 index 0000000000..912b86be25 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.html @@ -0,0 +1,17 @@ +
\ No newline at end of file diff --git a/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.scss b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.scss new file mode 100644 index 0000000000..736febabf3 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.scss @@ -0,0 +1,17 @@ +.favorite-list { + &__group { + border-bottom: 1px solid rgba(0, 0, 0, .2); + margin-bottom: 30px; + padding-bottom: 30px; + } + &__endpoint-card { + margin-bottom: 10px; + min-height: 200px; + } + &__entities { + width: 100%; + } + &__empty-text { + margin-bottom: 20px; + } +} \ No newline at end of file diff --git a/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.spec.ts b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.spec.ts new file mode 100644 index 0000000000..ae4f2103d0 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FavoritesGlobalListComponent } from './favorites-global-list.component'; +import { BaseTestModules } from '../../../test-framework/cloud-foundry-endpoint-service.helper'; + +describe('FavoritesGlobalListComponent', () => { + let component: FavoritesGlobalListComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [...BaseTestModules], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FavoritesGlobalListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.ts b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.ts new file mode 100644 index 0000000000..55c28a460f --- /dev/null +++ b/src/frontend/app/shared/components/favorites-global-list/favorites-global-list.component.ts @@ -0,0 +1,66 @@ +import { Component, OnInit } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { combineLatest, Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { IFavoriteEntity, IGroupedFavorites, UserFavoriteManager } from '../../../core/user-favorite-manager'; +import { AppState } from '../../../store/app-state'; +import { fetchingFavoritesSelector, errorFetchingFavoritesSelector } from '../../../store/selectors/favorite-groups.selectors'; + +interface IFavoritesInfo { + fetching: boolean; + error: boolean; +} + +@Component({ + selector: 'app-favorites-global-list', + templateUrl: './favorites-global-list.component.html', + styleUrls: ['./favorites-global-list.component.scss'] +}) +export class FavoritesGlobalListComponent implements OnInit { + public favInfo$: Observable; + public favoriteGroups$: Observable; + constructor(private store: Store) { } + + ngOnInit() { + const manager = new UserFavoriteManager(this.store); + this.favoriteGroups$ = manager.hydrateAllFavorites().pipe( + map(favs => this.sortFavoriteGroups(favs)) + ); + + this.favInfo$ = combineLatest( + this.store.select(fetchingFavoritesSelector), + this.store.select(errorFetchingFavoritesSelector) + ).pipe( + map(([fetching, error]) => ({ + fetching, + error + })) + ); + } + + private sortFavoriteGroups(entityGroups: IGroupedFavorites[]) { + if (!entityGroups) { + return entityGroups; + } + return entityGroups.map(group => { + if (group.entities) { + group.entities = group.entities.sort(this.sortFavoriteGroup); + } + return group; + }); + } + + private sortFavoriteGroup(entityA: IFavoriteEntity, entityB: IFavoriteEntity) { + if (entityA.favorite.entityType < entityB.favorite.entityType) { + return -1; + } + if (entityA.favorite.entityType > entityB.favorite.entityType) { + return 1; + } + return 0; + } + + public trackByEndpointId(index: number, group: IGroupedFavorites) { + return group.endpoint.favorite.guid; + } +} diff --git a/src/frontend/app/shared/components/favorites-meta-card/favorite-config-mapper.ts b/src/frontend/app/shared/components/favorites-meta-card/favorite-config-mapper.ts new file mode 100644 index 0000000000..6a88f75509 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-meta-card/favorite-config-mapper.ts @@ -0,0 +1,131 @@ +import { Observable } from 'rxjs'; +import { IRequestAction } from '../../../store/types/request.types'; +import { IFavoriteMetadata, IFavoriteTypeInfo, UserFavorite } from '../../../store/types/user-favorites.types'; +import { MetaCardMenuItem } from '../list/list-cards/meta-card/meta-card-base/meta-card.component'; +import { endpointSchemaKey } from '../../../store/helpers/entity-factory'; + +export interface IFavoriteTypes { + type: string; + prettyName: string; +} + +/** + * [label, value] + */ +export type TFavoritesMetaCardLine = [string, string | Observable]; + +export interface IFavoritesMetaCardConfig { + type: string; + lines?: TFavoritesMetaCardLine[]; + routerLink?: string; + name: string; + menuItems?: MetaCardMenuItem[]; +} + +export type TFavoriteMapperFunction = (entity: T) => IFavoritesMetaCardConfig; + +interface IFavoriteMappers { + [key: string]: { + mapper: TFavoriteMapperFunction, + prettyName: string, + actionGenerator: TFavoriteActionGenerator + entityToMetadata: TEntityToMetadata, + favoriteInfo: IFavoriteTypeInfo + }; +} + +export type TFavoriteActionGenerator = (favorite: UserFavorite) => IRequestAction; + +export type TEntityToMetadata = (entity: T) => Q; +export interface IFavoriteActionGenerators { + [key: string]: TFavoriteActionGenerator; +} +/** + * Stores the config used to hydrator and render favorites. + */ +class FavoritesConfigMapper { + private mapperKeySeparator = '-'; + private mappers: IFavoriteMappers = {}; + public getMapperKeyFromFavoriteInfo(favoriteInfo: IFavoriteTypeInfo) { + const { endpointType, entityType } = favoriteInfo; + return [endpointType, entityType].join(this.mapperKeySeparator); + } + + /** + * Register config used to manage a given favorite type + * @param favoriteInfo Base id information about the favorite this mapper will match + * @param prettyName The human readable name for the entity type + * @param mapper Takes an entity and maps it to favorite meta card config + * @param actionGenerator Takes a favorite and returns an action that can be used to hydrate the favorite + */ + public registerFavoriteConfig( + favoriteInfo: IFavoriteTypeInfo, + prettyName: string, + mapper: TFavoriteMapperFunction, + actionGenerator: TFavoriteActionGenerator, + entityToMetadata: TEntityToMetadata + ) { + const mapperKey = this.getMapperKeyFromFavoriteInfo(favoriteInfo); + this.mappers[mapperKey] = { + mapper, + prettyName, + actionGenerator, + entityToMetadata, + favoriteInfo + }; + } + /** + * For a given favorite, return the corresponding favorite meta card mapper + * @param favorite + */ + public getMapperFunction(favorite: IFavoriteTypeInfo) { + const mapperKey = this.getMapperKeyFromFavoriteInfo(favorite); + return this.mappers[mapperKey] ? this.mappers[mapperKey].mapper : null; + } + + /** + * For a given favorite, return the corresponding human readable type name + * @param favorite + */ + public getPrettyTypeName(favorite: IFavoriteTypeInfo) { + const mapperKey = this.getMapperKeyFromFavoriteInfo(favorite); + return this.mappers[mapperKey] ? this.mappers[mapperKey].prettyName : null; + } + + /** + * For a given favorite, return the corresponding hydration action + * @param favorite + */ + public getActionFromFavorite(favorite: UserFavorite) { + const mapperKey = this.getMapperKeyFromFavoriteInfo(favorite); + return this.mappers[mapperKey] ? this.mappers[mapperKey].actionGenerator(favorite) : null; + } + + /** + * For a given favorite, return the corresponding hydration action + * @param favorite + */ + public getEntityMetadata(favorite: IFavoriteTypeInfo, entity: T) { + const mapperKey = this.getMapperKeyFromFavoriteInfo(favorite); + return this.mappers[mapperKey] && this.mappers[mapperKey].entityToMetadata ? this.mappers[mapperKey].entityToMetadata(entity) : null; + } + + /** + * For a given endpoint type, return the list of possible favorite types + * @param favorite + */ + public getAllTypesForEndpoint(endpointType: string): IFavoriteTypes[] { + return Object.values(this.mappers).reduce((types: IFavoriteTypes[], mapper) => { + if (mapper.favoriteInfo.endpointType === endpointType && mapper.favoriteInfo.entityType !== endpointSchemaKey) { + types.push({ + type: mapper.favoriteInfo.entityType, + prettyName: mapper.prettyName + }); + } + return types; + }, []); + } + +} + +export const favoritesConfigMapper = new FavoritesConfigMapper(); diff --git a/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.html b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.html new file mode 100644 index 0000000000..d1cf486ec0 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.html @@ -0,0 +1,51 @@ + + +

+ {{ name$ | async }} +

+

+ {{ name$ | async }} +

+
{{ prettyName }}
+
+ + + {{ line[0] }} + {{ value }} + + +
+ +
Favorite not found
+ Could + not + fetch {{ prettyName | + lowercase }} + Endpoint + disconnected +
+
Type
+
{{ prettyName }}
+
ID
+
{{ favorite.entityId }}
+ +
+ +
+ + +
Favorite endpoint is not registered
+ + To unfavorite this endpoint, please unfavorite all child entities first. + +
+
ID
+
{{ favorite.endpointId }}
+
+ +
+ + + \ No newline at end of file diff --git a/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.scss b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.scss new file mode 100644 index 0000000000..4481bcbacc --- /dev/null +++ b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.scss @@ -0,0 +1,53 @@ +.fav-meta-card { + min-height: 160px; + outline: none; + &__header-text { + margin-top: 0; + } + &__type { + $type-height: 20px; + font-size: 13px; + line-height: $type-height; + margin-top: -($type-height - 2px); + opacity: .6; + } + &__missing { + align-items: center; + display: flex; + flex-direction: column; + height: 100%; + justify-content: space-around; + padding: 10px; + padding-top: 20px; + &-text { + font-size: 20px; + font-weight: bold; + } + &-small-text { + margin-bottom: 20px; + } + } + &__clickable { + cursor: pointer; + } + &__header { + white-space: nowrap; + } +} + +.error-details { + display: flex; + flex-direction: column; + padding: 0 20px; + &__value { + padding-bottom: 5px; + } + &__label { + font-size: 10px; + opacity: .6; + } +} + +.subtle-text { + opacity: .6; +} diff --git a/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.spec.ts b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.spec.ts new file mode 100644 index 0000000000..7895600814 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FavoritesMetaCardComponent } from './favorites-meta-card.component'; +import { BaseTestModules } from '../../../test-framework/cloud-foundry-endpoint-service.helper'; + +describe('FavoritesMetaCardComponent', () => { + let component: FavoritesMetaCardComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [...BaseTestModules], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FavoritesMetaCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.ts b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.ts new file mode 100644 index 0000000000..2bfe46c5c1 --- /dev/null +++ b/src/frontend/app/shared/components/favorites-meta-card/favorites-meta-card.component.ts @@ -0,0 +1,137 @@ +import { Component, Input } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { isObservable, Observable, of as observableOf } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { IFavoriteEntity } from '../../../core/user-favorite-manager'; +import { RemoveUserFavoriteAction } from '../../../store/actions/user-favourites-actions/remove-user-favorite-action'; +import { AppState } from '../../../store/app-state'; +import { entityFactory, userFavoritesSchemaKey } from '../../../store/helpers/entity-factory'; +import { endpointEntitiesSelector } from '../../../store/selectors/endpoint.selectors'; +import { IFavoriteMetadata, UserFavorite } from '../../../store/types/user-favorites.types'; +import { CardStatus, ComponentEntityMonitorConfig } from '../../shared.types'; +import { ConfirmationDialogConfig } from '../confirmation-dialog.config'; +import { ConfirmationDialogService } from '../confirmation-dialog.service'; +import { MetaCardMenuItem } from '../list/list-cards/meta-card/meta-card-base/meta-card.component'; +import { IFavoritesMetaCardConfig } from './favorite-config-mapper'; + + +@Component({ + selector: 'app-favorites-meta-card', + templateUrl: './favorites-meta-card.component.html', + styleUrls: ['./favorites-meta-card.component.scss'] +}) +export class FavoritesMetaCardComponent { + @Input() + public compact = false; + + @Input() + public placeholder = false; + + @Input() + public endpoint = false; + + @Input() + public endpointHasEntities = false; + + @Input() + public endpointDisconnected = false; + + public config: IFavoritesMetaCardConfig; + + public status$: Observable; + + public favorite: UserFavorite; + + /* + We use this to pass the favorite to the metacard, this dictates if we should show the favorite star or not. + We do not want to show the favorite star for endpoints that have favorite entities. + */ + public metaFavorite: UserFavorite; + + public entityConfig: ComponentEntityMonitorConfig; + + public showMore: boolean; + + public prettyName: string; + + public confirmation: ConfirmationDialogConfig; + + public endpointConnected$: Observable; + public name$: Observable; + public routerLink$: Observable; + public actions$: Observable; + + @Input() + set favoriteEntity(favoriteEntity: IFavoriteEntity) { + if (!this.placeholder && favoriteEntity) { + const endpoint$ = this.store.select(endpointEntitiesSelector).pipe( + map(endpoints => endpoints[favoriteEntity.favorite.endpointId]) + ); + this.endpointConnected$ = endpoint$.pipe(map(endpoint => !!endpoint.user)); + this.actions$ = this.endpointConnected$.pipe( + map(connected => connected ? this.config.menuItems : []) + ); + const { cardMapper, favorite, prettyName } = favoriteEntity; + this.favorite = favorite; + this.metaFavorite = !this.endpoint || (this.endpoint && !this.endpointHasEntities) ? favorite : null; + this.prettyName = prettyName; + this.entityConfig = new ComponentEntityMonitorConfig(favorite.guid, entityFactory(userFavoritesSchemaKey)); + + this.setConfirmation(prettyName, favorite); + + const config = cardMapper && favorite && favorite.metadata ? cardMapper(favorite.metadata) : null; + if (config) { + if (this.endpoint) { + this.name$ = endpoint$.pipe(map(endpoint => config.name + (endpoint.user ? '' : ' (Disconnected)'))); + this.routerLink$ = endpoint$.pipe(map(endpoint => endpoint.user ? config.routerLink : '/endpoints')); + } else { + this.name$ = observableOf(config.name); + this.routerLink$ = endpoint$.pipe(map(endpoint => endpoint.user ? config.routerLink : null)); + } + config.lines = this.mapLinesToObservables(config.lines); + this.config = config; + } + } + } + + constructor(private store: Store, private confirmDialog: ConfirmationDialogService) { } + + public setConfirmation(prettyName: string, favorite: UserFavorite) { + this.confirmation = new ConfirmationDialogConfig( + `Unfavorite ${prettyName}`, + `Are you sure you would like to unfavorite this ${prettyName.toLocaleLowerCase()} with the id ${favorite.entityId}?`, + 'Yes', + true + ); + } + + public confirmFavoriteRemoval() { + this.confirmDialog.open(this.confirmation, this.removeFavorite); + } + + private removeFavorite = () => { + this.store.dispatch(new RemoveUserFavoriteAction(this.favorite)); + } + + public toggleMoreError() { + this.showMore = !this.showMore; + } + + private mapLinesToObservables(lines: [string, string | Observable][]) { + if (!lines) { + return []; + } + return lines.map(line => { + const [label, value] = line; + if (!isObservable(value)) { + return [ + label, + observableOf(value) + ] as [string, Observable]; + } + return line; + }); + } + +} diff --git a/src/frontend/app/shared/components/list/list-cards/card.types.ts b/src/frontend/app/shared/components/list/list-cards/card.types.ts index e83cc52d06..0d18268026 100644 --- a/src/frontend/app/shared/components/list/list-cards/card.types.ts +++ b/src/frontend/app/shared/components/list/list-cards/card.types.ts @@ -4,5 +4,5 @@ import { CardsComponent } from './cards.component'; export const listCardComponents = [ CardsComponent, CardComponent, - ...listCards, + ...listCards ]; diff --git a/src/frontend/app/shared/components/list/list-cards/card/card.component.ts b/src/frontend/app/shared/components/list/list-cards/card/card.component.ts index 3c20ba85d7..4d2071fa2a 100644 --- a/src/frontend/app/shared/components/list/list-cards/card/card.component.ts +++ b/src/frontend/app/shared/components/list/list-cards/card/card.component.ts @@ -12,23 +12,22 @@ import { } from '@angular/core'; import { IListDataSource } from '../../data-sources-controllers/list-data-source-types'; -import { - AppServiceBindingCardComponent, -} from '../../list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component'; + +import { CardCell } from '../../list.types'; import { CardAppComponent } from '../../list-types/app/card/card-app.component'; -import { CfBuildpackCardComponent } from '../../list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component'; import { EndpointCardComponent } from '../../list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component'; import { CfOrgCardComponent } from '../../list-types/cf-orgs/cf-org-card/cf-org-card.component'; +import { CfSpaceCardComponent } from '../../list-types/cf-spaces/cf-space-card/cf-space-card.component'; +import { CfBuildpackCardComponent } from '../../list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component'; import { - CfSecurityGroupsCardComponent, + CfSecurityGroupsCardComponent } from '../../list-types/cf-security-groups/cf-security-groups-card/cf-security-groups-card.component'; -import { CfServiceCardComponent } from '../../list-types/cf-services/cf-service-card/cf-service-card.component'; -import { CfSpaceCardComponent } from '../../list-types/cf-spaces/cf-space-card/cf-space-card.component'; import { CfStacksCardComponent } from '../../list-types/cf-stacks/cf-stacks-card/cf-stacks-card.component'; +import { CfServiceCardComponent } from '../../list-types/cf-services/cf-service-card/cf-service-card.component'; import { - ServiceInstanceCardComponent, -} from '../../list-types/services-wall/service-instance-card/service-instance-card.component'; -import { CardCell } from '../../list.types'; + AppServiceBindingCardComponent +} from '../../list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component'; +import { ServiceInstanceCardComponent } from '../../list-types/services-wall/service-instance-card/service-instance-card.component'; export const listCards = [ CardAppComponent, @@ -42,13 +41,12 @@ export const listCards = [ AppServiceBindingCardComponent, ServiceInstanceCardComponent ]; - @Component({ selector: 'app-card', templateUrl: './card.component.html', styleUrls: ['./card.component.scss'], entryComponents: [ - ...listCards, + ...listCards ] }) export class CardComponent implements OnInit, OnChanges { diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html index f8fc534f40..1573840d12 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html @@ -13,16 +13,21 @@
- +
-
+ + +
- @@ -30,7 +35,7 @@
- + @@ -41,6 +46,6 @@
- + \ No newline at end of file diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss index b969de7045..52924821d4 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss @@ -29,14 +29,18 @@ display: flex; flex-direction: row; padding-bottom: 4px; + word-break: break-all; &__button { - position: absolute; - right: 7px; - top: 22px; + margin-right: -10px; + margin-top: -8px; } } + &__favorite { + opacity: .6; + } + &__header-container { &__title, diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts index ae3a112506..0c33221317 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts @@ -3,6 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { MetaCardComponent } from './meta-card.component'; import { SharedModule } from '../../../../../shared.module'; import { createBasicStoreModule } from '../../../../../../test-framework/store-test-helper'; +import { StoreModule } from '@ngrx/store'; describe('MetaCardComponent', () => { let component: MetaCardComponent; @@ -12,6 +13,7 @@ describe('MetaCardComponent', () => { TestBed.configureTestingModule({ imports: [ SharedModule, + StoreModule, createBasicStoreModule() ] }) diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts index 8d0603581d..1db78c4b9a 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts @@ -1,11 +1,16 @@ import { Component, ContentChild, ContentChildren, Input, QueryList } from '@angular/core'; +import { Store } from '@ngrx/store'; import { combineLatest, Observable, of as observableOf } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { first, map, tap } from 'rxjs/operators'; +import { getFavoriteFromCfEntity } from '../../../../../../core/user-favorite-helpers'; +import { UserFavoriteManager } from '../../../../../../core/user-favorite-manager'; +import { UserFavorite, IFavoriteMetadata } from '../../../../../../store/types/user-favorites.types'; import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; import { CardStatus, ComponentEntityMonitorConfig } from '../../../../../shared.types'; import { MetaCardItemComponent } from '../meta-card-item/meta-card-item.component'; import { MetaCardTitleComponent } from '../meta-card-title/meta-card-title.component'; +import { AppState } from './../../../../../../store/app-state'; export interface MetaCardMenuItem { @@ -32,6 +37,14 @@ export class MetaCardComponent { @Input() status$: Observable; + @Input() + public favorite: UserFavorite; + + @Input() + public confirmFavoriteRemoval = false; + + userFavoriteManager: UserFavoriteManager; + @Input() statusIcon = true; @Input() @@ -48,22 +61,31 @@ export class MetaCardComponent { entityConfig.schema ); this.isDeleting$ = entityMonitor.isDeletingEntity$; + if (!this.favorite) { + entityMonitor.entity$.pipe( + first(), + tap(entity => this.favorite = getFavoriteFromCfEntity(entity, entityConfig.schema.key)) + ).subscribe(); + } } + } public isDeleting$: Observable = observableOf(false); @Input('actionMenu') set actionMenu(actionMenu: MetaCardMenuItem[]) { - this._actionMenu = actionMenu.map(menuItem => { - if (!menuItem.can) { - menuItem.can = observableOf(true); - } - return menuItem; - }); - this.showMenu$ = combineLatest(actionMenu.map(menuItem => menuItem.can)).pipe( - map(cans => cans.some(can => can)) - ); + if (actionMenu) { + this._actionMenu = actionMenu.map(menuItem => { + if (!menuItem.can) { + menuItem.can = observableOf(true); + } + return menuItem; + }); + this.showMenu$ = combineLatest(actionMenu.map(menuItem => menuItem.can)).pipe( + map(cans => cans.some(can => can)) + ); + } } public _actionMenu: MetaCardMenuItem[]; @@ -72,7 +94,10 @@ export class MetaCardComponent { @Input() clickAction: Function = null; - constructor(private entityMonitorFactory: EntityMonitorFactory) { + constructor( + private entityMonitorFactory: EntityMonitorFactory, + store: Store + ) { if (this.actionMenu) { this.actionMenu = this.actionMenu.map(element => { if (!element.disabled) { @@ -81,6 +106,7 @@ export class MetaCardComponent { return element; }); } + this.userFavoriteManager = new UserFavoriteManager(store); } cancelPropagation = (event) => { diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-key/meta-card-key.component.html b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-key/meta-card-key.component.html index a4bd3d8f63..5cbbdb3c26 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-key/meta-card-key.component.html +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-key/meta-card-key.component.html @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.html b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.html new file mode 100644 index 0000000000..bffcbca5d2 --- /dev/null +++ b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.scss b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.scss new file mode 100644 index 0000000000..a43f558379 --- /dev/null +++ b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.scss @@ -0,0 +1,5 @@ + +.table-cell-favorite { + display: flex; + justify-content: flex-end; +} diff --git a/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.spec.ts b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.spec.ts new file mode 100644 index 0000000000..49c121b94a --- /dev/null +++ b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.spec.ts @@ -0,0 +1,31 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BaseTestModulesNoShared } from '../../../../../test-framework/cloud-foundry-endpoint-service.helper'; +import { TableCellFavoriteComponent } from './table-cell-favorite.component'; + +describe('TableCellFavoriteComponent', () => { + let component: TableCellFavoriteComponent; + let fixture: ComponentFixture>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + TableCellFavoriteComponent, + ], + imports: [ + ...BaseTestModulesNoShared + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TableCellFavoriteComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.ts b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.ts new file mode 100644 index 0000000000..f7f6ea3674 --- /dev/null +++ b/src/frontend/app/shared/components/list/list-table/table-cell-favorite/table-cell-favorite.component.ts @@ -0,0 +1,59 @@ +import { Component, Input } from '@angular/core'; + +import { UserFavorite, IFavoriteMetadata } from '../../../../../store/types/user-favorites.types'; +import { TableCellCustom } from '../../list.types'; +import { ITableColumn } from '../table.types'; +import { favoritesConfigMapper } from '../../../favorites-meta-card/favorite-config-mapper'; + +export interface TableCellFavoriteComponentConfig { + createUserFavorite: (entity: T) => UserFavorite; +} + +@Component({ + selector: 'app-table-cell-favorite', + templateUrl: './table-cell-favorite.component.html', + styleUrls: ['./table-cell-favorite.component.scss'] +}) +export class TableCellFavoriteComponent extends TableCellCustom { + + public favorite: UserFavorite; + public canFavorite = false; + + private _config: TableCellFavoriteComponentConfig; + @Input('config') + get config() { return this._config; } + set config(config: TableCellFavoriteComponentConfig) { + this._config = config; + this.createUserFavorite(); + } + + private _row: T; + @Input('row') + get row() { return this._row; } + set row(row: T) { + this._row = row; + this.createUserFavorite(); + } + + private createUserFavorite() { + if (this.row && this.config) { + this.favorite = this.config.createUserFavorite(this.row); + this.canFavorite = !!favoritesConfigMapper.getMapperFunction(this.favorite); + } + } +} + +export function createTableColumnFavorite( + createUserFavorite: (entity: T) => UserFavorite +): ITableColumn { + const cellConfig: TableCellFavoriteComponentConfig = { + createUserFavorite + }; + return { + columnId: 'favorite', + headerCell: () => '', + cellComponent: TableCellFavoriteComponent, + cellFlex: '0 0 100px', + cellConfig + }; +} diff --git a/src/frontend/app/shared/components/list/list-table/table-cell/table-cell.component.ts b/src/frontend/app/shared/components/list/list-table/table-cell/table-cell.component.ts index 11e3c193c5..5adb3debd4 100644 --- a/src/frontend/app/shared/components/list/list-table/table-cell/table-cell.component.ts +++ b/src/frontend/app/shared/components/list/list-table/table-cell/table-cell.component.ts @@ -28,8 +28,6 @@ import { } from '../../list-types/app-event/table-cell-event-type/table-cell-event-type.component'; import { TableCellCfCellComponent } from '../../list-types/app-instance/table-cell-cf-cell/table-cell-cf-cell.component'; import { TableCellUsageComponent } from '../../list-types/app-instance/table-cell-usage/table-cell-usage.component'; -import { TableCellRouteComponent } from '../../list-types/cf-routes/table-cell-route/table-cell-route.component'; -import { TableCellTCPRouteComponent } from '../../list-types/cf-routes/table-cell-tcproute/table-cell-tcproute.component'; import { TableCellEditVariableComponent, } from '../../list-types/app-variables/table-cell-edit-variable/table-cell-edit-variable.component'; @@ -56,6 +54,8 @@ import { import { TableCellRouteAppsAttachedComponent, } from '../../list-types/cf-routes/table-cell-route-apps-attached/table-cell-route-apps-attached.component'; +import { TableCellRouteComponent } from '../../list-types/cf-routes/table-cell-route/table-cell-route.component'; +import { TableCellTCPRouteComponent } from '../../list-types/cf-routes/table-cell-tcproute/table-cell-tcproute.component'; import { TableCellServiceInstanceAppsAttachedComponent, } from '../../list-types/cf-spaces-service-instances/table-cell-service-instance-apps-attached/table-cell-service-instance-apps-attached.component'; @@ -109,6 +109,7 @@ import { TableCellDefaultComponent } from '../app-table-cell-default/app-table-c import { TableCellActionsComponent } from '../table-cell-actions/table-cell-actions.component'; import { TableCellBooleanIndicatorComponent } from '../table-cell-boolean-indicator/table-cell-boolean-indicator.component'; import { TableCellEditComponent } from '../table-cell-edit/table-cell-edit.component'; +import { TableCellFavoriteComponent } from '../table-cell-favorite/table-cell-favorite.component'; import { TableCellRadioComponent } from '../table-cell-radio/table-cell-radio.component'; import { TableCellRequestMonitorIconComponent, @@ -162,7 +163,8 @@ export const listTableCells = [ TableCellEndpointIsAdminComponent, TableCellAServicePlanPublicComponent, TableCellAServicePlanPriceComponent, - TableCellAServicePlanExtrasComponent + TableCellAServicePlanExtrasComponent, + TableCellFavoriteComponent ]; @Component({ diff --git a/src/frontend/app/shared/components/list/list-table/table-header-select/table-header-select.component.ts b/src/frontend/app/shared/components/list/list-table/table-header-select/table-header-select.component.ts index 80c8586e45..12f8663ff1 100644 --- a/src/frontend/app/shared/components/list/list-table/table-header-select/table-header-select.component.ts +++ b/src/frontend/app/shared/components/list/list-table/table-header-select/table-header-select.component.ts @@ -1,5 +1,5 @@ -/* tslint:disable:no-access-missing-member https://github.com/mgechev/codelyzer/issues/191*/ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; + import { TableCellCustom } from '../../list.types'; @Component({ diff --git a/src/frontend/app/shared/components/list/list-table/table.component.ts b/src/frontend/app/shared/components/list/list-table/table.component.ts index 6e58b7c7ad..d0dae7983f 100644 --- a/src/frontend/app/shared/components/list/list-table/table.component.ts +++ b/src/frontend/app/shared/components/list/list-table/table.component.ts @@ -11,8 +11,7 @@ import { TableCellSelectComponent } from './table-cell-select/table-cell-select. import { TableHeaderSelectComponent } from './table-header-select/table-header-select.component'; import { ITableColumn } from './table.types'; - -const tableColumnSelect = { +const tableColumnSelect: ITableColumn = { columnId: 'select', headerCellComponent: TableHeaderSelectComponent, cellComponent: TableCellSelectComponent, @@ -20,7 +19,7 @@ const tableColumnSelect = { cellFlex: '0 0 60px' }; -const tableColumnAction = { +const tableColumnAction: ITableColumn = { columnId: 'actions', headerCell: () => '', cellComponent: TableCellActionsComponent, diff --git a/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.html b/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.html index dea79be898..7160d79df6 100644 --- a/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.html +++ b/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.html @@ -1,4 +1,4 @@ - + {{ row.entity.name }} @@ -18,7 +18,8 @@ CF/Org/Space - {{endpointName$ | async }}/{{ row.entity.space.entity.organization.entity.name }}/{{ row.entity.space.entity.name }} + {{endpointName$ | async }}/{{ row.entity.space.entity.organization.entity.name }}/{{ row.entity.space.entity.name + }} @@ -35,4 +36,4 @@ {{ row.metadata.created_at | date:'medium' }} - + \ No newline at end of file diff --git a/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.ts b/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.ts index d536f3f489..6d3ffcbae0 100644 --- a/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.ts +++ b/src/frontend/app/shared/components/list/list-types/app/card/card-app.component.ts @@ -4,6 +4,7 @@ import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; import { IApp } from '../../../../../../core/cf-api.types'; +import { getFavoriteFromCfEntity } from '../../../../../../core/user-favorite-helpers'; import { ApplicationService } from '../../../../../../features/applications/application.service'; import { haveMultiConnectedCfs } from '../../../../../../features/cloud-foundry/cf.helpers'; import { AppState } from '../../../../../../store/app-state'; @@ -11,9 +12,11 @@ import { applicationSchemaKey, endpointSchemaKey, entityFactory } from '../../.. import { selectEntity } from '../../../../../../store/selectors/api.selectors'; import { APIResource } from '../../../../../../store/types/api.types'; import { EndpointModel } from '../../../../../../store/types/endpoint.types'; +import { UserFavorite } from '../../../../../../store/types/user-favorites.types'; import { CardStatus, ComponentEntityMonitorConfig } from '../../../../../shared.types'; import { ApplicationStateData, ApplicationStateService } from '../../../../application-state/application-state.service'; import { CardCell } from '../../../list.types'; +import { IAppFavMetadata } from '../../../../../../cf-favourite-types'; @Component({ selector: 'app-card-app', @@ -30,6 +33,8 @@ export class CardAppComponent extends CardCell> implements OnI multipleConnectedEndpoints$: Observable; entityConfig: ComponentEntityMonitorConfig; + public favorite: UserFavorite; + constructor( private store: Store, private appStateService: ApplicationStateService @@ -45,6 +50,8 @@ export class CardAppComponent extends CardCell> implements OnI map(endpoint => endpoint ? endpoint.name : '') ); + this.favorite = getFavoriteFromCfEntity(this.row, applicationSchemaKey); + const initState = this.appStateService.get(this.row.entity, null); this.applicationState$ = ApplicationService.getApplicationState( this.store, diff --git a/src/frontend/app/shared/components/list/list-types/app/cf-app-config.service.ts b/src/frontend/app/shared/components/list/list-types/app/cf-app-config.service.ts index 1cc7d3351d..c6d2475ce4 100644 --- a/src/frontend/app/shared/components/list/list-types/app/cf-app-config.service.ts +++ b/src/frontend/app/shared/components/list/list-types/app/cf-app-config.service.ts @@ -4,11 +4,15 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { filter, first, map, switchMap } from 'rxjs/operators'; +import { IApp } from '../../../../../core/cf-api.types'; import { UtilsService } from '../../../../../core/utils.service'; import { ListView } from '../../../../../store/actions/list.actions'; import { AppState } from '../../../../../store/app-state'; +import { applicationSchemaKey } from '../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../store/types/api.types'; +import { UserFavorite, IFavoriteMetadata } from '../../../../../store/types/user-favorites.types'; import { CfOrgSpaceDataService, createCfOrgSpaceFilterConfig } from '../../../../data-services/cf-org-space-service.service'; +import { createTableColumnFavorite } from '../../list-table/table-cell-favorite/table-cell-favorite.component'; import { ITableColumn } from '../../list-table/table.types'; import { IListConfig, IListMultiFilterConfig, ListConfig, ListViewTypes } from '../../list.component.types'; import { CardAppComponent } from './card/card-app.component'; @@ -56,7 +60,7 @@ export class CfAppConfigService extends ListConfig implements IList } appsDataSource: CfAppsDataSource; - columns: Array> = [ + columns: Array>> = [ { columnId: 'name', headerCell: () => 'Name', cellComponent: TableCellAppNameComponent, cellFlex: '2', sort: { type: 'sort', @@ -115,6 +119,14 @@ export class CfAppConfigService extends ListConfig implements IList }, cellFlex: '2' }, + createTableColumnFavorite((row: APIResource): UserFavorite => { + return new UserFavorite( + row.entity.cfGuid, + 'cf', + applicationSchemaKey, + row.entity.guid, + ); + }), ]; viewType = ListViewTypes.BOTH; text = { diff --git a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.html b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.html index 4da1b5d28c..6b87693173 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.html +++ b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.html @@ -1,4 +1,4 @@ - + {{ row.name }} Address @@ -14,4 +14,4 @@ - + \ No newline at end of file diff --git a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts index 3ccc432a43..2ac1550240 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts @@ -5,6 +5,8 @@ import { getEndpointTypes, getFullEndpointApiUrl } from '../../../../../../featu import { EndpointModel } from '../../../../../../store/types/endpoint.types'; import { CardStatus } from '../../../../../shared.types'; import { CardCell } from '../../../list.types'; +import { getFavoriteFromCfEntity, getFavoriteFromEndpointEntity } from '../../../../../../core/user-favorite-helpers'; +import { UserFavoriteEndpoint } from '../../../../../../store/types/user-favorites.types'; @Component({ @@ -19,13 +21,15 @@ export class EndpointCardComponent extends CardCell implements On public status$ = new ReplaySubject(); @Input() - row: EndpointModel; + public row: EndpointModel; + public favorite: UserFavoriteEndpoint; constructor() { super(); } ngOnInit() { + this.favorite = getFavoriteFromEndpointEntity(this.row); this.status$.next(this.mapStatus(this.row)); } diff --git a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html index ef18f1a1d8..669101f9cb 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html +++ b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html @@ -1,4 +1,4 @@ - + {{ row.entity.name }} diff --git a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts index cfbe4fa1a1..d186a24649 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts @@ -7,6 +7,7 @@ import { IApp, IOrganization } from '../../../../../../core/cf-api.types'; import { getStartedAppInstanceCount } from '../../../../../../core/cf.helpers'; import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; +import { getFavoriteFromCfEntity } from '../../../../../../core/user-favorite-helpers'; import { truthyIncludingZeroString } from '../../../../../../core/utils.service'; import { getOrgRolesString } from '../../../../../../features/cloud-foundry/cf.helpers'; import { @@ -19,6 +20,7 @@ import { AppState } from '../../../../../../store/app-state'; import { entityFactory, organizationSchemaKey } from '../../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../../store/types/api.types'; import { EndpointUser } from '../../../../../../store/types/endpoint.types'; +import { IFavoriteMetadata, UserFavorite } from '../../../../../../store/types/user-favorites.types'; import { createUserRoleInOrg } from '../../../../../../store/types/user.types'; import { CfUserService } from '../../../../../data-services/cf-user.service'; import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; @@ -48,6 +50,7 @@ export class CfOrgCardComponent extends CardCell> imp userRolesInOrg: string; currentUser$: Observable; public entityConfig: ComponentEntityMonitorConfig; + public favorite: UserFavorite; public orgStatus$: Observable; constructor( @@ -87,6 +90,8 @@ export class CfOrgCardComponent extends CardCell> imp map(u => getOrgRolesString(u)), ); + this.favorite = getFavoriteFromCfEntity(this.row, organizationSchemaKey); + const allApps$: Observable[]> = this.cfEndpointService.appsPagObs.hasEntities$.pipe( switchMap(hasAll => hasAll ? this.cfEndpointService.getAppsInOrgViaAllApps(this.row) : observableOf(null)) ); diff --git a/src/frontend/app/shared/components/list/list-types/cf-space-apps/cf-space-apps-list-config.service.ts b/src/frontend/app/shared/components/list/list-types/cf-space-apps/cf-space-apps-list-config.service.ts index 4e8bb249a5..0b6e3984fe 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-space-apps/cf-space-apps-list-config.service.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-space-apps/cf-space-apps-list-config.service.ts @@ -6,12 +6,16 @@ import { IApp } from '../../../../../core/cf-api.types'; import { CloudFoundrySpaceService } from '../../../../../features/cloud-foundry/services/cloud-foundry-space.service'; import { ListView } from '../../../../../store/actions/list.actions'; import { AppState } from '../../../../../store/app-state'; +import { applicationSchemaKey } from '../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../store/types/api.types'; +import { UserFavorite } from '../../../../../store/types/user-favorites.types'; +import { createTableColumnFavorite } from '../../list-table/table-cell-favorite/table-cell-favorite.component'; import { ITableColumn } from '../../list-table/table.types'; import { defaultPaginationPageSizeOptionsTable, IListConfig, ListViewTypes } from '../../list.component.types'; import { TableCellAppNameComponent } from '../app/table-cell-app-name/table-cell-app-name.component'; import { TableCellAppStatusComponent } from '../app/table-cell-app-status/table-cell-app-status.component'; import { CfSpaceAppsDataSource } from './cf-space-apps-data-source.service'; +import { ISpaceFavMetadata } from '../../../../../cf-favourite-types'; @Injectable() export class CfSpaceAppsListConfigService implements IListConfig { @@ -62,6 +66,14 @@ export class CfSpaceAppsListConfigService implements IListConfig { }, cellFlex: '2' }, + createTableColumnFavorite((row: APIResource): UserFavorite => { + return new UserFavorite( + row.entity.cfGuid, + 'cf', + applicationSchemaKey, + row.entity.guid, + ); + }), ] constructor( diff --git a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html index c8c3ee5566..b1dc4a4ada 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html +++ b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html @@ -1,4 +1,4 @@ - + {{ row.entity.name }} diff --git a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts index 0eb9331d7d..e576afef43 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts @@ -7,6 +7,7 @@ import { IApp, ISpace } from '../../../../../../core/cf-api.types'; import { getStartedAppInstanceCount } from '../../../../../../core/cf.helpers'; import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; +import { getFavoriteFromCfEntity } from '../../../../../../core/user-favorite-helpers'; import { truthyIncludingZeroString } from '../../../../../../core/utils.service'; import { getSpaceRolesString } from '../../../../../../features/cloud-foundry/cf.helpers'; import { @@ -22,6 +23,7 @@ import { AppState } from '../../../../../../store/app-state'; import { entityFactory, spaceSchemaKey } from '../../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../../store/types/api.types'; import { EndpointUser } from '../../../../../../store/types/endpoint.types'; +import { UserFavorite } from '../../../../../../store/types/user-favorites.types'; import { CfUserService } from '../../../../../data-services/cf-user.service'; import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; import { PaginationMonitorFactory } from '../../../../../monitors/pagination-monitor.factory'; @@ -30,6 +32,7 @@ import { ConfirmationDialogConfig } from '../../../../confirmation-dialog.config import { ConfirmationDialogService } from '../../../../confirmation-dialog.service'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../list.types'; +import { ISpaceFavMetadata } from '../../../../../../cf-favourite-types'; @Component({ @@ -53,6 +56,7 @@ export class CfSpaceCardComponent extends CardCell> implemen userRolesInSpace: string; currentUser$: Observable; entityConfig: ComponentEntityMonitorConfig; + favorite: UserFavorite; spaceStatus$: Observable; constructor( @@ -72,6 +76,7 @@ export class CfSpaceCardComponent extends CardCell> implemen this.spaceGuid = this.row.metadata.guid; this.entityConfig = new ComponentEntityMonitorConfig(this.spaceGuid, entityFactory(spaceSchemaKey)); this.orgGuid = this.cfOrgService.orgGuid; + this.favorite = getFavoriteFromCfEntity(this.row, spaceSchemaKey); this.cardMenu = [ { label: 'Edit', diff --git a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-spaces-list-config.service.ts b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-spaces-list-config.service.ts index e8346f4843..faf8326823 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-spaces-list-config.service.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-spaces-list-config.service.ts @@ -43,6 +43,7 @@ export class CfSpacesListConfigService implements IListConfig { }, }]; + constructor( private store: Store, cfOrgService: CloudFoundryOrganizationService, diff --git a/src/frontend/app/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts b/src/frontend/app/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts index f49043ffcd..39801b9f2a 100644 --- a/src/frontend/app/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts +++ b/src/frontend/app/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts @@ -21,11 +21,13 @@ import { AppState } from '../../../../../store/app-state'; import { EndpointsEffect } from '../../../../../store/effects/endpoint.effects'; import { selectDeletionInfo, selectUpdateInfo } from '../../../../../store/selectors/api.selectors'; import { EndpointModel, endpointStoreNames } from '../../../../../store/types/endpoint.types'; +import { UserFavorite, UserFavoriteEndpoint } from '../../../../../store/types/user-favorites.types'; import { EntityMonitorFactory } from '../../../../monitors/entity-monitor.factory.service'; import { InternalEventMonitorFactory } from '../../../../monitors/internal-event-monitor.factory'; import { PaginationMonitorFactory } from '../../../../monitors/pagination-monitor.factory'; import { ConfirmationDialogConfig } from '../../../confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../confirmation-dialog.service'; +import { createTableColumnFavorite } from '../../list-table/table-cell-favorite/table-cell-favorite.component'; import { ITableColumn } from '../../list-table/table.types'; import { IListAction, IListConfig, ListViewTypes } from '../../list.component.types'; import { EndpointsDataSource } from './endpoints-data-source'; @@ -189,7 +191,9 @@ export class EndpointsListConfigService implements IListConfig { private globalActions = []; - columns = endpointColumns; + columns = [ + ...endpointColumns + ]; isLocal = true; dataSource: EndpointsDataSource; viewType = ListViewTypes.TABLE_ONLY; @@ -236,6 +240,14 @@ export class EndpointsListConfigService implements IListConfig { private currentUserPermissionsService: CurrentUserPermissionsService, private confirmDialog: ConfirmationDialogService ) { + const favoriteCell = createTableColumnFavorite( + (row: EndpointModel) => new UserFavoriteEndpoint( + row.guid, + row.cnsi_type, + row + ) + ); + this.columns.push(favoriteCell); this.dataSource = new EndpointsDataSource( this.store, this, diff --git a/src/frontend/app/shared/components/list/list-types/service-plans/service-plans-list-config.service.ts b/src/frontend/app/shared/components/list/list-types/service-plans/service-plans-list-config.service.ts index d1b966b4f5..43b586f45b 100644 --- a/src/frontend/app/shared/components/list/list-types/service-plans/service-plans-list-config.service.ts +++ b/src/frontend/app/shared/components/list/list-types/service-plans/service-plans-list-config.service.ts @@ -3,13 +3,11 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { IServicePlan } from '../../../../../core/cf-api-svc.types'; -import { CurrentUserPermissionsService } from '../../../../../core/current-user-permissions.service'; import { getServicePlanName } from '../../../../../features/service-catalog/services-helper'; import { ServicesService } from '../../../../../features/service-catalog/services.service'; import { ListView } from '../../../../../store/actions/list.actions'; import { AppState } from '../../../../../store/app-state'; import { APIResource } from '../../../../../store/types/api.types'; -import { ServiceActionHelperService } from '../../../../data-services/service-action-helper.service'; import { IListDataSource } from '../../data-sources-controllers/list-data-source-types'; import { ITableColumn } from '../../list-table/table.types'; import { defaultPaginationPageSizeOptionsTable, IListConfig, ListViewTypes } from '../../list.component.types'; diff --git a/src/frontend/app/shared/components/list/list.component.html b/src/frontend/app/shared/components/list/list.component.html index a7acf2dfa3..42495ebd02 100644 --- a/src/frontend/app/shared/components/list/list.component.html +++ b/src/frontend/app/shared/components/list/list.component.html @@ -2,7 +2,8 @@
- +
{{ @@ -15,7 +16,8 @@
- @@ -28,7 +30,8 @@
- + {{ multiFilterManager.allLabel }} {{selectItem.label}} @@ -43,29 +46,34 @@
- +
- + {{column.headerCell()}} - -
- @@ -89,14 +97,17 @@
- -
-
@@ -104,18 +115,23 @@
-
- - + +
- +
@@ -129,7 +145,8 @@ -
{{config.text?.maxedResults || 'There are too many results. Please use the filters to reduce the number of results.'}}
+
{{config.text?.maxedResults || 'There are too many results. Please use the filters to + reduce the number of results.'}}
diff --git a/src/frontend/app/shared/components/metrics-parent-range-selector/metrics-parent-range-selector.component.spec.ts b/src/frontend/app/shared/components/metrics-parent-range-selector/metrics-parent-range-selector.component.spec.ts index 07158364bc..95e85e7ed5 100644 --- a/src/frontend/app/shared/components/metrics-parent-range-selector/metrics-parent-range-selector.component.spec.ts +++ b/src/frontend/app/shared/components/metrics-parent-range-selector/metrics-parent-range-selector.component.spec.ts @@ -1,6 +1,5 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { DateFormatPipe } from 'ngx-moment'; import { CoreModule } from '../../../core/core.module'; import { createBasicStoreModule } from '../../../test-framework/store-test-helper'; @@ -16,7 +15,7 @@ describe('MetricsParentRangeSelectorComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [MetricsParentRangeSelectorComponent, StartEndDateComponent, DateFormatPipe, DateTimeComponent], + declarations: [MetricsParentRangeSelectorComponent, StartEndDateComponent, DateTimeComponent], imports: [ CoreModule, createBasicStoreModule(), diff --git a/src/frontend/app/shared/components/metrics-range-selector/metrics-range-selector.component.spec.ts b/src/frontend/app/shared/components/metrics-range-selector/metrics-range-selector.component.spec.ts index d6c3f56933..e529a8b4b7 100644 --- a/src/frontend/app/shared/components/metrics-range-selector/metrics-range-selector.component.spec.ts +++ b/src/frontend/app/shared/components/metrics-range-selector/metrics-range-selector.component.spec.ts @@ -1,6 +1,5 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { DateFormatPipe } from 'ngx-moment'; import { CoreModule } from '../../../core/core.module'; import { createBasicStoreModule } from '../../../test-framework/store-test-helper'; @@ -16,7 +15,7 @@ describe('MetricsRangeSelectorComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [MetricsRangeSelectorComponent, StartEndDateComponent, DateFormatPipe, DateTimeComponent], + declarations: [MetricsRangeSelectorComponent, StartEndDateComponent, DateTimeComponent], imports: [ CoreModule, createBasicStoreModule(), diff --git a/src/frontend/app/shared/components/no-content-message/no-content-message.component.scss b/src/frontend/app/shared/components/no-content-message/no-content-message.component.scss index 029fcab709..11ede3ba81 100644 --- a/src/frontend/app/shared/components/no-content-message/no-content-message.component.scss +++ b/src/frontend/app/shared/components/no-content-message/no-content-message.component.scss @@ -27,7 +27,7 @@ &__link { display: flex; position: absolute; - right: 74px; + right: 113px; top: 54px; &-icon { font-size: 44px; diff --git a/src/frontend/app/shared/components/page-header/page-header-events/page-header-events.component.ts b/src/frontend/app/shared/components/page-header/page-header-events/page-header-events.component.ts index f0f9dee0a3..9804c545dd 100644 --- a/src/frontend/app/shared/components/page-header/page-header-events/page-header-events.component.ts +++ b/src/frontend/app/shared/components/page-header/page-header-events/page-header-events.component.ts @@ -8,10 +8,9 @@ import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators'; import { ToggleHeaderEvent } from '../../../../store/actions/dashboard-actions'; import { AppState } from '../../../../store/app-state'; import { endpointSchemaKey, entityFactory } from '../../../../store/helpers/entity-factory'; -import { CloudFoundryService } from '../../../data-services/cloud-foundry.service'; import { InternalEventMonitorFactory } from '../../../monitors/internal-event-monitor.factory'; import { PaginationMonitor } from '../../../monitors/pagination-monitor'; -import { EndpointModel } from '../../../../store/types/endpoint.types'; +import { EndpointModel, endpointListKey } from '../../../../store/types/endpoint.types'; @Component({ @@ -42,7 +41,6 @@ export class PageHeaderEventsComponent implements OnInit { constructor( private internalEventMonitorFactory: InternalEventMonitorFactory, - public cloudFoundryService: CloudFoundryService, private activatedRoute: ActivatedRoute, private store: Store ) { @@ -62,7 +60,7 @@ export class PageHeaderEventsComponent implements OnInit { } if (this.endpointIds$) { const endpointMonitor = new PaginationMonitor( - this.store, CloudFoundryService.EndpointList, entityFactory(endpointSchemaKey) + this.store, endpointListKey, entityFactory(endpointSchemaKey) ); const cfEndpointEventMonitor = this.internalEventMonitorFactory.getMonitor(endpointSchemaKey, this.endpointIds$); this.errorMessage$ = combineLatest( diff --git a/src/frontend/app/shared/components/page-header/page-header.component.html b/src/frontend/app/shared/components/page-header/page-header.component.html index 2f7954f7ba..c399540a19 100644 --- a/src/frontend/app/shared/components/page-header/page-header.component.html +++ b/src/frontend/app/shared/components/page-header/page-header.component.html @@ -16,6 +16,8 @@
+ +
@@ -29,6 +31,15 @@ "> | + + +
+

Recent

+ +
+
diff --git a/src/frontend/app/shared/components/page-header/page-header.component.scss b/src/frontend/app/shared/components/page-header/page-header.component.scss index f9769f4d89..3425fe895f 100644 --- a/src/frontend/app/shared/components/page-header/page-header.component.scss +++ b/src/frontend/app/shared/components/page-header/page-header.component.scss @@ -6,6 +6,9 @@ $bottom-index: $top-index - 1; $breadcrumb-padding: 3px; position: relative; z-index: $top-index; + &__history { + padding: 0 20px 20px; + } &__nav-toggle-wrapper { margin-right: 20px; } @@ -90,6 +93,10 @@ $bottom-index: $top-index - 1; max-width: 400px; min-width: 200px; } + &__favorite { + margin-bottom: -2px; + margin-left: 10px; + } } .mat-toolbar-row, diff --git a/src/frontend/app/shared/components/page-header/page-header.component.ts b/src/frontend/app/shared/components/page-header/page-header.component.ts index 9062753cf9..1e406035fa 100644 --- a/src/frontend/app/shared/components/page-header/page-header.component.ts +++ b/src/frontend/app/shared/components/page-header/page-header.component.ts @@ -1,3 +1,4 @@ +import { UserFavorite, IFavoriteMetadata } from './../../../store/types/user-favorites.types'; import { Component, Input } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; @@ -10,6 +11,8 @@ import { ISubHeaderTabs } from '../page-subheader/page-subheader.types'; import { ToggleSideNav } from './../../../store/actions/dashboard-actions'; import { AppState } from './../../../store/app-state'; import { BREADCRUMB_URL_PARAM, IHeaderBreadcrumb, IHeaderBreadcrumbLink } from './page-header.types'; +import { AddRecentlyVisitedEntityAction } from '../../../store/actions/recently-visited.actions'; +import { favoritesConfigMapper } from '../favorites-meta-card/favorite-config-mapper'; @Component({ selector: 'app-page-header', @@ -20,6 +23,7 @@ export class PageHeaderComponent { public breadcrumbDefinitions: IHeaderBreadcrumbLink[] = null; private breadcrumbKey: string; public eventSeverity = InternalEventSeverity; + public _favorite: UserFavorite; @Input() hideSideNavButton = false; @@ -33,6 +37,34 @@ export class PageHeaderComponent { @Input() showUnderFlow = false; + @Input() showHistory = true; + + @Input() set favorite(favorite: UserFavorite) { + if (favorite && (!this._favorite || (favorite.guid !== this._favorite.guid))) { + this._favorite = favorite; + const mapperFunction = favoritesConfigMapper.getMapperFunction(favorite); + const prettyType = favoritesConfigMapper.getPrettyTypeName(favorite); + const prettyEndpointType = favoritesConfigMapper.getPrettyTypeName({ + endpointType: favorite.endpointType, + entityType: 'endpoint' + }); + if (mapperFunction) { + const { name, routerLink } = mapperFunction(favorite.metadata); + this.store.dispatch(new AddRecentlyVisitedEntityAction({ + guid: favorite.guid, + entityType: favorite.entityType, + endpointType: favorite.endpointType, + entityId: favorite.entityId, + name, + routerLink, + prettyType, + endpointId: favorite.endpointId, + prettyEndpointType: prettyEndpointType === prettyType ? null : prettyEndpointType + })); + } + } + } + public userNameFirstLetter$: Observable; public username$: Observable; public actionsKey: String; diff --git a/src/frontend/app/shared/components/page-header/page-header.module.ts b/src/frontend/app/shared/components/page-header/page-header.module.ts index ff6beac46d..f2fb6ffff6 100644 --- a/src/frontend/app/shared/components/page-header/page-header.module.ts +++ b/src/frontend/app/shared/components/page-header/page-header.module.ts @@ -1,21 +1,21 @@ import { NgModule } from '@angular/core'; import { CoreModule } from '../../../core/core.module'; -import { PageHeaderComponent } from './page-header.component'; +import { ExtensionButtonsComponent } from '../extension-buttons/extension-buttons.component'; import { PageSubheaderComponent } from '../page-subheader/page-subheader.component'; import { PageHeaderEventsComponent } from './page-header-events/page-header-events.component'; -import { ExtensionButtonsComponent } from '../extension-buttons/extension-buttons.component'; +import { PageHeaderComponent } from './page-header.component'; @NgModule({ imports: [ - CoreModule + CoreModule, ], declarations: [ ExtensionButtonsComponent, PageSubheaderComponent, PageHeaderComponent, - PageHeaderEventsComponent, + PageHeaderEventsComponent ], exports: [ ExtensionButtonsComponent, diff --git a/src/frontend/app/shared/components/recent-entities/recent-entities.component.html b/src/frontend/app/shared/components/recent-entities/recent-entities.component.html new file mode 100644 index 0000000000..047885cc10 --- /dev/null +++ b/src/frontend/app/shared/components/recent-entities/recent-entities.component.html @@ -0,0 +1,56 @@ + + + +
+
+
+ {{ + countedEntity.entity.name }} + +
{{ countedEntity.entity.name }}
+
+
+ {{ countedEntity.subText$ | async }} +
+
+
+
+
+ + + +
+
+ +
+
+ +
+
+ + +
+
+
+ {{ + countedEntity.entity.name }} + +
{{ countedEntity.entity.name }}
+
+
+ {{ countedEntity.mostRecentHit | amTimeAgo }} +
+
+ {{ countedEntity.subText$ | async }} +
+
+
+
+
+ + + No recent activity + \ No newline at end of file diff --git a/src/frontend/app/shared/components/recent-entities/recent-entities.component.scss b/src/frontend/app/shared/components/recent-entities/recent-entities.component.scss new file mode 100644 index 0000000000..88f583825a --- /dev/null +++ b/src/frontend/app/shared/components/recent-entities/recent-entities.component.scss @@ -0,0 +1,35 @@ +$spacing: 10px; +.type-info { + font-size: 12px; + line-height: 20px; + opacity: .6; +} +.recent-entity { + outline: 0; + padding: $spacing; + & + & { + border-top: 1px solid rgba(0, 0, 0, .08); + } + &__favorite { + margin-left: auto; + } + &:focus, + &:hover { + background-color: rgba(0, 0, 0, .02); + } + + &--name { + word-break: break-all; + } +} + +.clickable { + cursor: pointer; +} + +.recent-tab { + padding-top: $spacing; + &.standalone { + padding-top: 0; + } +} diff --git a/src/frontend/app/shared/components/recent-entities/recent-entities.component.spec.ts b/src/frontend/app/shared/components/recent-entities/recent-entities.component.spec.ts new file mode 100644 index 0000000000..8c4b4e24ec --- /dev/null +++ b/src/frontend/app/shared/components/recent-entities/recent-entities.component.spec.ts @@ -0,0 +1,30 @@ +import { MDAppModule } from './../../../core/md.module'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RecentEntitiesComponent } from './recent-entities.component'; +import { RouterTestingModule } from '@angular/router/testing'; +import { CommonModule } from '@angular/common'; +import { CoreModule } from '../../../core/core.module'; +import { createBasicStoreModule } from '../../../test-framework/store-test-helper'; + +describe('RecentEntitiesComponent', () => { + let component: RecentEntitiesComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [RouterTestingModule, CoreModule, CommonModule, createBasicStoreModule()] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RecentEntitiesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/app/shared/components/recent-entities/recent-entities.component.ts b/src/frontend/app/shared/components/recent-entities/recent-entities.component.ts new file mode 100644 index 0000000000..cbd84ec287 --- /dev/null +++ b/src/frontend/app/shared/components/recent-entities/recent-entities.component.ts @@ -0,0 +1,174 @@ +import { Component, Input } from '@angular/core'; +import { Store } from '@ngrx/store'; +import * as moment from 'moment'; +import { Observable, of as observableOf } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; + +import { endpointSchemaKey } from '../../../store/helpers/entity-factory'; +import { endpointEntitiesSelector } from '../../../store/selectors/endpoint.selectors'; +import { recentlyVisitedSelector } from '../../../store/selectors/recently-visitied.selectors'; +import { IEntityHit, IRecentlyVisitedEntity, IRecentlyVisitedState } from '../../../store/types/recently-visited.types'; +import { AppState } from './../../../store/app-state'; + +interface IRelevanceModifier { + time: number; + modifier: number; +} +interface IRelevanceModifiers { + high: IRelevanceModifier; + medium: IRelevanceModifier; + low: IRelevanceModifier; +} + +class RenderableRecent { + public mostRecentHit: moment.Moment; + public subText$: Observable; + constructor(readonly entity: IRecentlyVisitedEntity, private store: Store) { + if (entity.entityType === endpointSchemaKey) { + this.subText$ = observableOf(entity.prettyType); + } else { + this.subText$ = this.store.select(endpointEntitiesSelector).pipe( + map(endpoints => { + if (Object.keys(endpoints).length > 1) { + return `${entity.prettyType} - ${endpoints[entity.endpointId].name} (${entity.prettyEndpointType})`; + } + return entity.prettyType; + }) + ); + } + } +} + +class CountedRecentEntity { + public count = 0; + public mostRecentHitUnix: number; + public guid: string; + private checkAndSetDate(date: number) { + if (!this.mostRecentHitUnix || date > this.mostRecentHitUnix) { + this.mostRecentHitUnix = date; + } + } + public applyHit(hit: IEntityHit, modifier?: number) { + const amount = modifier ? 1 * modifier : 1; + this.count += amount; + this.checkAndSetDate(hit.date); + } + constructor(hit: IEntityHit) { + this.guid = hit.guid; + this.checkAndSetDate(hit.date); + } +} + +class CountedRecentEntitiesManager { + private countedRecentEntities: CountedRecentEntities = {}; + private relevanceModifiers: IRelevanceModifiers; + private renderableRecents: { + [guid: string]: RenderableRecent + }; + + constructor(recentState: IRecentlyVisitedState, private store: Store) { + const { entities, hits } = recentState; + const mostRecentTime = hits[0] ? moment(hits[0].date) : moment(); + + this.relevanceModifiers = { + high: { + time: mostRecentTime.subtract(30, 'minute').unix(), + modifier: 2 + }, + medium: { + time: mostRecentTime.subtract(1, 'day').unix(), + modifier: 1.5 + }, + low: { + time: mostRecentTime.subtract(1, 'week').unix(), + modifier: 1 + } + }; + + this.renderableRecents = Object.keys(entities).reduce((renderableRecents, recentGuid) => { + renderableRecents[recentGuid] = new RenderableRecent(entities[recentGuid], store); + return renderableRecents; + }, {}); + + this.addHits(hits); + } + + private addHits(hits: IEntityHit[]) { + hits.forEach(hit => { + this.addHit(hit); + }); + Object.keys(this.renderableRecents).forEach( + guid => { + if (this.countedRecentEntities[guid]) { + this.renderableRecents[guid].mostRecentHit = moment(this.countedRecentEntities[guid].mostRecentHitUnix); + } + } + ); + } + + private getModifier(recentEntity: IEntityHit) { + if (recentEntity.date < this.relevanceModifiers.low.time) { + return this.relevanceModifiers.low.modifier; + } + if (recentEntity.date < this.relevanceModifiers.medium.time) { + return this.relevanceModifiers.medium.modifier; + } + return this.relevanceModifiers.high.modifier; + } + + public addHit(recentEntity: IEntityHit) { + const modifier = this.getModifier(recentEntity); + if (!this.countedRecentEntities[recentEntity.guid]) { + this.countedRecentEntities[recentEntity.guid] = new CountedRecentEntity(recentEntity); + } + this.countedRecentEntities[recentEntity.guid].applyHit(recentEntity, modifier); + } + + private sort(sortKey: 'count' | 'mostRecentHitUnix' = 'count') { + const sortedHits = Object.values(this.countedRecentEntities) + .sort((countedA, countedB) => countedB[sortKey] - countedA[sortKey]) + .map(counted => counted); + return sortedHits.map(entity => this.renderableRecents[entity.guid]); + } + + public getFrecentEntities(): RenderableRecent[] { + return this.sort(); + } + + public getRecentEntities(): RenderableRecent[] { + return this.sort('mostRecentHitUnix'); + } +} +interface CountedRecentEntities { + [entityId: string]: CountedRecentEntity; +} + +@Component({ + selector: 'app-recent-entities', + templateUrl: './recent-entities.component.html', + styleUrls: ['./recent-entities.component.scss'] +}) +export class RecentEntitiesComponent { + @Input() + public history = false; + + public recentEntities$: Observable; + public frecentEntities$: Observable; + public hasHits$: Observable; + constructor(store: Store) { + const recentEntities$ = store.select(recentlyVisitedSelector); + this.hasHits$ = recentEntities$.pipe( + map(recentEntities => !!recentEntities.hits && recentEntities.hits.length > 0) + ); + const entitiesManager$ = recentEntities$.pipe( + filter(recentEntities => !!recentEntities.hits && recentEntities.hits.length > 0), + map(recentEntities => new CountedRecentEntitiesManager(recentEntities, store)), + ); + this.frecentEntities$ = entitiesManager$.pipe( + map(manager => manager.getFrecentEntities()), + ); + this.recentEntities$ = entitiesManager$.pipe( + map(manager => manager.getRecentEntities()) + ); + } +} diff --git a/src/frontend/app/shared/data-services/cloud-foundry.service.ts b/src/frontend/app/shared/data-services/cloud-foundry.service.ts index 36f50e543d..67b458b441 100644 --- a/src/frontend/app/shared/data-services/cloud-foundry.service.ts +++ b/src/frontend/app/shared/data-services/cloud-foundry.service.ts @@ -6,13 +6,12 @@ import { map } from 'rxjs/operators'; import { AppState } from '../../store/app-state'; import { endpointSchemaKey, entityFactory } from '../../store/helpers/entity-factory'; import { APIResource, EntityInfo } from '../../store/types/api.types'; -import { EndpointModel } from '../../store/types/endpoint.types'; +import { EndpointModel, endpointListKey } from '../../store/types/endpoint.types'; import { PaginationMonitor } from '../monitors/pagination-monitor'; import { PaginationMonitorFactory } from '../monitors/pagination-monitor.factory'; @Injectable() export class CloudFoundryService { - static EndpointList = 'endpoint-list'; hasRegisteredCFEndpoints$: Observable; hasConnectedCFEndpoints$: Observable; connectedCFEndpoints$: Observable; @@ -21,11 +20,11 @@ export class CloudFoundryService { waitForAppEntity$: Observable>; constructor( - private store: Store, - private paginationMonitorFactory: PaginationMonitorFactory + store: Store, + paginationMonitorFactory: PaginationMonitorFactory ) { - this.cfEndpointsMonitor = new PaginationMonitor(store, CloudFoundryService.EndpointList, entityFactory(endpointSchemaKey)); + this.cfEndpointsMonitor = new PaginationMonitor(store, endpointListKey, entityFactory(endpointSchemaKey)); this.cFEndpoints$ = this.cfEndpointsMonitor.currentPage$.pipe( map(endpoints => endpoints.filter(e => e.cnsi_type === 'cf')) diff --git a/src/frontend/app/shared/data-services/scm/gitlab-scm.ts b/src/frontend/app/shared/data-services/scm/gitlab-scm.ts index d5750bb211..913f465bb1 100644 --- a/src/frontend/app/shared/data-services/scm/gitlab-scm.ts +++ b/src/frontend/app/shared/data-services/scm/gitlab-scm.ts @@ -1,16 +1,17 @@ -import { GitSCM, SCMIcon } from './scm'; +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Observable, of as observableOf } from 'rxjs'; import { map } from 'rxjs/operators'; -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { GitSCMType } from './scm.service'; import { Md5 } from 'ts-md5/dist/md5'; -import { GitRepo, GitCommit, GitBranch } from '../../../store/types/git.types'; + +import { GitBranch, GitCommit, GitRepo } from '../../../store/types/git.types'; +import { GitSCM, SCMIcon } from './scm'; +import { GitSCMType } from './scm.service'; const gitLabAPIUrl = 'https://gitlab.com/api/v4'; export class GitLabSCM implements GitSCM { - constructor(public httpClient: HttpClient) {} + constructor(public httpClient: HttpClient) { } getType(): GitSCMType { return 'gitlab'; diff --git a/src/frontend/app/shared/monitors/pagination-monitor.ts b/src/frontend/app/shared/monitors/pagination-monitor.ts index 4f7718b4b6..73a32e5f59 100644 --- a/src/frontend/app/shared/monitors/pagination-monitor.ts +++ b/src/frontend/app/shared/monitors/pagination-monitor.ts @@ -37,6 +37,9 @@ export class PaginationMonitor { */ public pagination$: Observable; + + public currentPageIds$: Observable; + constructor( private store: Store, public paginationKey: string, @@ -95,6 +98,7 @@ export class PaginationMonitor { schema.key, paginationKey, ); + this.currentPageIds$ = this.createPagIdObservable(this.pagination$); this.currentPage$ = this.createPageObservable(this.pagination$, schema); this.currentPageError$ = this.createErrorObservable(this.pagination$); this.fetchingCurrentPage$ = this.createFetchingObservable(this.pagination$); @@ -111,6 +115,15 @@ export class PaginationMonitor { ); } + private createPagIdObservable( + pagination$: Observable + ) { + return pagination$.pipe( + distinctUntilChanged(this.isPageSameIsh), + map(pagination => pagination.ids[pagination.currentPage] || []) + ); + } + private createPageObservable( pagination$: Observable, schema: normalizrSchema.Entity, diff --git a/src/frontend/app/shared/shared.module.ts b/src/frontend/app/shared/shared.module.ts index 43772d53a4..653ab0e819 100644 --- a/src/frontend/app/shared/shared.module.ts +++ b/src/frontend/app/shared/shared.module.ts @@ -5,7 +5,6 @@ import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; import { NgxChartsModule } from '@swimlane/ngx-charts'; -import { MomentModule } from 'ngx-moment'; import { MaterialDesignFrameworkModule } from 'stratos-angular6-json-schema-form'; import { CoreModule } from '../core/core.module'; @@ -74,6 +73,9 @@ import { EditableDisplayValueComponent } from './components/editable-display-val import { EndpointsMissingComponent } from './components/endpoints-missing/endpoints-missing.component'; import { EnumerateComponent } from './components/enumerate/enumerate.component'; import { EnvVarViewComponent } from './components/env-var-view/env-var-view.component'; +import { FavoritesEntityListComponent } from './components/favorites-entity-list/favorites-entity-list.component'; +import { FavoritesGlobalListComponent } from './components/favorites-global-list/favorites-global-list.component'; +import { FavoritesMetaCardComponent } from './components/favorites-meta-card/favorites-meta-card.component'; import { FileInputComponent } from './components/file-input/file-input.component'; import { FocusDirective } from './components/focus.directive'; import { GithubCommitAuthorComponent } from './components/github-commit-author/github-commit-author.component'; @@ -144,6 +146,7 @@ import { ValuesPipe } from './pipes/values.pipe'; import { MetricsRangeSelectorService } from './services/metrics-range-selector.service'; import { UserPermissionDirective } from './user-permission.directive'; + @NgModule({ imports: [ CommonModule, @@ -155,7 +158,6 @@ import { UserPermissionDirective } from './user-permission.directive'; CdkTableModule, NgxChartsModule, MaterialDesignFrameworkModule, - MomentModule, ], declarations: [ LoadingPageComponent, @@ -253,7 +255,10 @@ import { UserPermissionDirective } from './user-permission.directive'; StartEndDateComponent, MetricsRangeSelectorComponent, MetricsParentRangeSelectorComponent, - MultilineTitleComponent, + FavoritesGlobalListComponent, + FavoritesMetaCardComponent, + FavoritesEntityListComponent, + MultilineTitleComponent ], exports: [ FormsModule, @@ -347,12 +352,14 @@ import { UserPermissionDirective } from './user-permission.directive'; DateTimeComponent, StartEndDateComponent, MetricsRangeSelectorComponent, - MetricsParentRangeSelectorComponent + MetricsParentRangeSelectorComponent, + FavoritesMetaCardComponent, + FavoritesGlobalListComponent ], entryComponents: [ DialogConfirmComponent, EnvVarViewComponent, - NoServicePlansComponent + NoServicePlansComponent, ], providers: [ ListConfig, @@ -365,6 +372,7 @@ import { UserPermissionDirective } from './user-permission.directive'; CloudFoundryService, InternalEventMonitorFactory, ServiceActionHelperService, + MetricsRangeSelectorService, GitSCMService, MetricsRangeSelectorService ] diff --git a/src/frontend/app/store/actions/endpoint.actions.ts b/src/frontend/app/store/actions/endpoint.actions.ts index fe172756a6..d15004cbd9 100644 --- a/src/frontend/app/store/actions/endpoint.actions.ts +++ b/src/frontend/app/store/actions/endpoint.actions.ts @@ -1,10 +1,10 @@ import { Action } from '@ngrx/store'; import { endpointSchemaKey } from '../helpers/entity-factory'; -import { EndpointModel, INewlyConnectedEndpointInfo } from '../types/endpoint.types'; +import { EndpointModel, INewlyConnectedEndpointInfo, endpointListKey } from '../types/endpoint.types'; import { PaginatedAction } from '../types/pagination.types'; -import { CloudFoundryService } from '../../shared/data-services/cloud-foundry.service'; import { EndpointType } from '../../core/extension/extension-types'; +import { NormalizedResponse } from '../types/api.types'; export const GET_ENDPOINTS = '[Endpoints] Get all'; export const GET_ENDPOINTS_START = '[Endpoints] Get all start'; @@ -56,7 +56,7 @@ export interface AuthParamsToken { export type AuthParams = AuthParamsUsernamePassword | AuthParamsToken; export class GetAllEndpoints implements PaginatedAction { - public static storeKey = CloudFoundryService.EndpointList; + public static storeKey = endpointListKey; constructor(public login = false) { } entityKey = endpointSchemaKey; paginationKey = GetAllEndpoints.storeKey; @@ -75,7 +75,7 @@ export class GetAllEndpoints implements PaginatedAction { } export class GetAllEndpointsSuccess implements Action { - constructor(public payload: {}, public login = false) { } + constructor(public payload: NormalizedResponse, public login = false) { } type = GET_ENDPOINTS_SUCCESS; } diff --git a/src/frontend/app/store/actions/pagination.actions.ts b/src/frontend/app/store/actions/pagination.actions.ts index 72c11d9224..33e9819e86 100644 --- a/src/frontend/app/store/actions/pagination.actions.ts +++ b/src/frontend/app/store/actions/pagination.actions.ts @@ -17,6 +17,7 @@ export const SET_INITIAL_PARAMS = '[Pagination] Set initial params'; export const ADD_PARAMS = '[Pagination] Add Params'; export const REMOVE_PARAMS = '[Pagination] Remove Params'; export const SET_PAGE_BUSY = '[Pagination] Set Page Busy'; +export const REMOVE_ID_FROM_PAGINATION = '[Pagination] Remove id from pagination'; export const UPDATE_MAXED_STATE = '[Pagination] Update maxed state'; export function getPaginationKey(type: string, id: string, endpointGuid?: string) { diff --git a/src/frontend/app/store/actions/recently-visited.actions.ts b/src/frontend/app/store/actions/recently-visited.actions.ts new file mode 100644 index 0000000000..2729da7119 --- /dev/null +++ b/src/frontend/app/store/actions/recently-visited.actions.ts @@ -0,0 +1,23 @@ +import { IRecentlyVisitedEntity, IRecentlyVisitedEntityDated } from '../types/recently-visited.types'; +import { Action } from '@ngrx/store'; +import * as moment from 'moment'; + +export class AddRecentlyVisitedEntityAction implements Action { + static ACTION_TYPE = '[Recently visited] Add'; + public type = AddRecentlyVisitedEntityAction.ACTION_TYPE; + public date: number; + public recentlyVisited: IRecentlyVisitedEntityDated; + constructor(recentlyVisited: IRecentlyVisitedEntity) { + this.recentlyVisited = { + ...recentlyVisited, + date: moment().valueOf() + }; + } +} + +export class SetRecentlyVisitedEntityAction implements Action { + static ACTION_TYPE = '[Recently visited] Set'; + public type = SetRecentlyVisitedEntityAction.ACTION_TYPE; + constructor(public recentlyVisited: IRecentlyVisitedEntity) { } +} + diff --git a/src/frontend/app/store/actions/user-favourites-actions/base-user-favorites-action.ts b/src/frontend/app/store/actions/user-favourites-actions/base-user-favorites-action.ts new file mode 100644 index 0000000000..c7bfabd239 --- /dev/null +++ b/src/frontend/app/store/actions/user-favourites-actions/base-user-favorites-action.ts @@ -0,0 +1,11 @@ +import { Action } from '@ngrx/store'; + +export class BaseUserFavoritesAction implements Action { + constructor( + actionType: string, + ) { + this.type = actionType; + } + public type: string; + public url = '/user-favorites'; +} diff --git a/src/frontend/app/store/actions/user-favourites-actions/get-user-favorites-action.ts b/src/frontend/app/store/actions/user-favourites-actions/get-user-favorites-action.ts new file mode 100644 index 0000000000..b0b3eed95b --- /dev/null +++ b/src/frontend/app/store/actions/user-favourites-actions/get-user-favorites-action.ts @@ -0,0 +1,30 @@ +import { BaseUserFavoritesAction } from './base-user-favorites-action'; +import { UserFavorite, IFavoriteMetadata } from '../../types/user-favorites.types'; + +export class GetUserFavoritesAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'GET_USER_FAVORITES'; + constructor() { + super( + GetUserFavoritesAction.ACTION_TYPE + ); + } +} + +export class GetUserFavoritesSuccessAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'GET_USER_FAVORITES_SUCCESS'; + constructor(public favorites: UserFavorite[]) { + super( + GetUserFavoritesSuccessAction.ACTION_TYPE + ); + } +} + +export class GetUserFavoritesFailedAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'GET_USER_FAVORITES_FAILED'; + constructor() { + super( + GetUserFavoritesFailedAction.ACTION_TYPE + ); + } +} + diff --git a/src/frontend/app/store/actions/user-favourites-actions/remove-user-favorite-action.ts b/src/frontend/app/store/actions/user-favourites-actions/remove-user-favorite-action.ts new file mode 100644 index 0000000000..89bcd7d47e --- /dev/null +++ b/src/frontend/app/store/actions/user-favourites-actions/remove-user-favorite-action.ts @@ -0,0 +1,21 @@ +import { BaseUserFavoritesAction } from './base-user-favorites-action'; +import { UserFavorite, IFavoriteMetadata } from '../../types/user-favorites.types'; + +export class RemoveUserFavoriteAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'REMOVE_USER_FAVORITE'; + constructor(public favorite: UserFavorite) { + super( + RemoveUserFavoriteAction.ACTION_TYPE + ); + } +} + +export class RemoveUserFavoriteSuccessAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'REMOVE_USER_FAVORITE_SUCCESS'; + constructor(public favorite: UserFavorite) { + super( + RemoveUserFavoriteSuccessAction.ACTION_TYPE + ); + } +} + diff --git a/src/frontend/app/store/actions/user-favourites-actions/save-user-favorite-action.ts b/src/frontend/app/store/actions/user-favourites-actions/save-user-favorite-action.ts new file mode 100644 index 0000000000..b38c8199de --- /dev/null +++ b/src/frontend/app/store/actions/user-favourites-actions/save-user-favorite-action.ts @@ -0,0 +1,25 @@ +import { IFavoriteMetadata } from './../../types/user-favorites.types'; +import { BaseUserFavoritesAction } from './base-user-favorites-action'; +import { UserFavorite } from '../../types/user-favorites.types'; + +export class SaveUserFavoriteAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'SAVE_USER_FAVORITE'; + constructor( + public favorite: UserFavorite + ) { + super( + SaveUserFavoriteAction.ACTION_TYPE + ); + } +} + +export class SaveUserFavoriteSuccessAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'SAVE_USER_FAVORITE_SUCCESS'; + constructor( + public favorite: UserFavorite + ) { + super( + SaveUserFavoriteSuccessAction.ACTION_TYPE + ); + } +} diff --git a/src/frontend/app/store/actions/user-favourites-actions/toggle-user-favorite-action.ts b/src/frontend/app/store/actions/user-favourites-actions/toggle-user-favorite-action.ts new file mode 100644 index 0000000000..03a6100d31 --- /dev/null +++ b/src/frontend/app/store/actions/user-favourites-actions/toggle-user-favorite-action.ts @@ -0,0 +1,13 @@ +import { BaseUserFavoritesAction } from './base-user-favorites-action'; +import { UserFavorite, IFavoriteMetadata } from '../../types/user-favorites.types'; + +export class ToggleUserFavoriteAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'TOGGLE_USER_FAVORITE'; + constructor( + public favorite: UserFavorite + ) { + super( + ToggleUserFavoriteAction.ACTION_TYPE + ); + } +} diff --git a/src/frontend/app/store/actions/user-favourites-actions/update-user-favorite-metadata-action.ts b/src/frontend/app/store/actions/user-favourites-actions/update-user-favorite-metadata-action.ts new file mode 100644 index 0000000000..3707f615f1 --- /dev/null +++ b/src/frontend/app/store/actions/user-favourites-actions/update-user-favorite-metadata-action.ts @@ -0,0 +1,21 @@ +import { UserFavorite, IFavoriteMetadata } from '../../types/user-favorites.types'; +import { BaseUserFavoritesAction } from './base-user-favorites-action'; + +export class UpdateUserFavoriteMetadataAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'UPDATE_FAVORITE_METADATA'; + constructor(public favorite: UserFavorite) { + super( + UpdateUserFavoriteMetadataAction.ACTION_TYPE + ); + } +} + +export class UpdateUserFavoriteMetadataSuccessAction extends BaseUserFavoritesAction { + static ACTION_TYPE = 'UPDATE_FAVORITE_METADATA_SUCCESS'; + constructor(public favorite: UserFavorite) { + super( + UpdateUserFavoriteMetadataSuccessAction.ACTION_TYPE + ); + } +} + diff --git a/src/frontend/app/store/app-state.ts b/src/frontend/app/store/app-state.ts index 600beb4c9d..d1b5d6d686 100644 --- a/src/frontend/app/store/app-state.ts +++ b/src/frontend/app/store/app-state.ts @@ -13,6 +13,8 @@ import { PaginationState } from './types/pagination.types'; import { RoutingHistory } from './types/routing.type'; import { UAASetupState } from './types/uaa-setup.types'; import { UsersRolesState } from './types/users-roles.types'; +import { IUserFavoritesGroupsState } from './types/favorite-groups.types'; +import { IRecentlyVisitedState } from './types/recently-visited.types'; export interface IRequestTypeState { [entityKey: string]: IRequestEntityTypeState; } @@ -36,4 +38,6 @@ export interface AppState { manageUsersRoles: UsersRolesState; internalEvents: InternalEventsState; currentUserRoles: ICurrentUserRolesState; + userFavoritesGroups: IUserFavoritesGroupsState; + recentlyVisited: IRecentlyVisitedState; } diff --git a/src/frontend/app/store/effects/endpoint.effects.ts b/src/frontend/app/store/effects/endpoint.effects.ts index e3c7c7a10b..2821ecab4c 100644 --- a/src/frontend/app/store/effects/endpoint.effects.ts +++ b/src/frontend/app/store/effects/endpoint.effects.ts @@ -3,7 +3,7 @@ import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular import { Injectable } from '@angular/core'; import { Actions, Effect } from '@ngrx/effects'; import { Store } from '@ngrx/store'; -import { catchError, mergeMap, tap } from 'rxjs/operators'; +import { catchError, mergeMap, tap, debounce, debounceTime } from 'rxjs/operators'; import { BrowserStandardEncoder } from '../../helper'; import { @@ -41,6 +41,7 @@ import { import { EndpointType } from '../../core/extension/extension-types'; import { SendClearEventAction } from '../actions/internal-events.actions'; import { endpointSchemaKey } from '../helpers/entity-factory'; +import { GetUserFavoritesAction } from '../actions/user-favourites-actions/get-user-favorites-action'; @Injectable() @@ -67,7 +68,7 @@ export class EndpointsEffect { [endpointStoreNames.type]: {} }, result: [] - } as NormalizedResponse; + } as NormalizedResponse; Object.keys(endpoints).forEach((type: string) => { const endpointsForType = endpoints[type]; @@ -122,8 +123,6 @@ export class EndpointsEffect { [CONNECT_ENDPOINTS_SUCCESS, CONNECT_ENDPOINTS_FAILED], action.endpointType, action.body, - ).pipe( - tap(() => this.clearEndpointInternalEvents(action.guid)) ); })); @@ -144,8 +143,6 @@ export class EndpointsEffect { null, [DISCONNECT_ENDPOINTS_SUCCESS, DISCONNECT_ENDPOINTS_FAILED], action.endpointType - ).pipe( - tap(() => this.clearEndpointInternalEvents(action.guid)) ); })); @@ -166,8 +163,6 @@ export class EndpointsEffect { 'delete', [UNREGISTER_ENDPOINTS_SUCCESS, UNREGISTER_ENDPOINTS_FAILED], action.endpointType - ).pipe( - tap(() => this.clearEndpointInternalEvents(action.guid)) ); })); @@ -206,7 +201,7 @@ export class EndpointsEffect { } return message; } - private getEndpointUpdateAction(guid, type, updatingKey) { + private getEndpointUpdateAction(guid: string, type: string, updatingKey: string) { return { entityKey: endpointStoreNames.type, guid, @@ -245,12 +240,20 @@ export class EndpointsEffect { if (actionStrings[0]) { actions.push(new EndpointActionComplete(actionStrings[0], apiAction.guid, endpointType, endpoint)); } + if (apiActionType === 'delete') { actions.push(new ClearPaginationOfEntity(apiAction.entityKey, apiAction.guid)); + actions.push(new GetUserFavoritesAction()); } + if (apiActionType === 'create') { actions.push(new GetSystemInfo()); } + + if (apiAction.updatingKey === EndpointsEffect.disconnectingKey || apiActionType === 'create' || apiActionType === 'delete') { + actions.push(this.clearEndpointInternalEvents(apiAction.guid)); + } + actions.push(new WrapperRequestActionSuccess(null, apiAction, apiActionType)); return actions; } @@ -267,14 +270,12 @@ export class EndpointsEffect { } private clearEndpointInternalEvents(guid: string) { - this.store.dispatch( - new SendClearEventAction( - endpointSchemaKey, - guid, - { - clean: true - } - ) + return new SendClearEventAction( + endpointSchemaKey, + guid, + { + clean: true + } ); } } diff --git a/src/frontend/app/store/effects/user-favorites-effect.ts b/src/frontend/app/store/effects/user-favorites-effect.ts new file mode 100644 index 0000000000..1b46c98497 --- /dev/null +++ b/src/frontend/app/store/effects/user-favorites-effect.ts @@ -0,0 +1,123 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Actions, Effect } from '@ngrx/effects'; +import { Store } from '@ngrx/store'; +import { catchError, first, map, mergeMap, switchMap } from 'rxjs/operators'; + +import { environment } from '../../../environments/environment'; +import { UserFavoriteManager } from '../../core/user-favorite-manager'; +import { ClearPaginationOfEntity } from '../actions/pagination.actions'; +import { + GetUserFavoritesAction, + GetUserFavoritesFailedAction, + GetUserFavoritesSuccessAction, +} from '../actions/user-favourites-actions/get-user-favorites-action'; +import { + RemoveUserFavoriteAction, + RemoveUserFavoriteSuccessAction, +} from '../actions/user-favourites-actions/remove-user-favorite-action'; +import { + SaveUserFavoriteAction, + SaveUserFavoriteSuccessAction, +} from '../actions/user-favourites-actions/save-user-favorite-action'; +import { ToggleUserFavoriteAction } from '../actions/user-favourites-actions/toggle-user-favorite-action'; +import { + UpdateUserFavoriteMetadataAction, + UpdateUserFavoriteMetadataSuccessAction, +} from '../actions/user-favourites-actions/update-user-favorite-metadata-action'; +import { AppState } from '../app-state'; +import { userFavoritesSchemaKey } from '../helpers/entity-factory'; +import { NormalizedResponse } from '../types/api.types'; +import { PaginatedAction } from '../types/pagination.types'; +import { WrapperRequestActionSuccess } from '../types/request.types'; +import { IFavoriteMetadata, UserFavorite, userFavoritesPaginationKey } from '../types/user-favorites.types'; + +const { proxyAPIVersion } = environment; +const favoriteUrlPath = `/pp/${proxyAPIVersion}/favorites`; + + +@Injectable() +export class UserFavoritesEffect { + + constructor( + private http: HttpClient, + private actions$: Actions, + private store: Store, + ) { } + + private userFavoriteManager = new UserFavoriteManager(this.store); + + @Effect() saveFavorite = this.actions$.ofType(SaveUserFavoriteAction.ACTION_TYPE).pipe( + mergeMap(action => { + return this.http.post>(favoriteUrlPath, action.favorite).pipe( + mergeMap(newFavorite => { + return [ + new SaveUserFavoriteSuccessAction(newFavorite) + ]; + }) + ); + }) + ); + + @Effect({ dispatch: false }) getFavorite$ = this.actions$.ofType(GetUserFavoritesAction.ACTION_TYPE).pipe( + switchMap((action: GetUserFavoritesAction) => { + const apiAction = { + entityKey: userFavoritesSchemaKey, + type: action.type + } as PaginatedAction; + return this.http.get[]>(favoriteUrlPath).pipe( + map(favorites => { + const mappedData = favorites.reduce>>((data, favorite) => { + const { guid } = favorite; + if (guid) { + data.entities[userFavoritesSchemaKey][guid] = favorite; + data.result.push(guid); + } + return data; + }, { entities: { [userFavoritesSchemaKey]: {} }, result: [] }); + this.store.dispatch(new WrapperRequestActionSuccess(mappedData, apiAction)); + this.store.dispatch(new GetUserFavoritesSuccessAction(favorites)); + }), + catchError(e => { + this.store.dispatch(new GetUserFavoritesFailedAction()); + throw e; + }) + ); + }) + ); + + @Effect() toggleFavorite = this.actions$.ofType(ToggleUserFavoriteAction.ACTION_TYPE).pipe( + mergeMap(action => + this.userFavoriteManager.getIsFavoriteObservable(action.favorite).pipe( + first(), + map(isFav => { + if (isFav) { + return new RemoveUserFavoriteAction(action.favorite); + } else { + return new SaveUserFavoriteAction(action.favorite); + } + }) + ) + ) + ); + + @Effect({ dispatch: false }) removeFavorite$ = this.actions$.ofType(RemoveUserFavoriteAction.ACTION_TYPE).pipe( + switchMap((action: RemoveUserFavoriteAction) => { + const { guid } = action.favorite; + this.store.dispatch(new RemoveUserFavoriteSuccessAction(action.favorite)); + this.store.dispatch(new ClearPaginationOfEntity(userFavoritesSchemaKey, guid, userFavoritesPaginationKey)); + return this.http.delete>(`${favoriteUrlPath}/${guid}`); + }) + ); + + @Effect() updateMetadata$ = this.actions$.ofType(UpdateUserFavoriteMetadataAction.ACTION_TYPE).pipe( + mergeMap((action: UpdateUserFavoriteMetadataAction) => { + return this.http.post>( + `${favoriteUrlPath}/${action.favorite.guid}/metadata`, + action.favorite.metadata + ).pipe( + map(() => new UpdateUserFavoriteMetadataSuccessAction(action.favorite)) + ); + }) + ); +} diff --git a/src/frontend/app/store/helpers/entity-factory.ts b/src/frontend/app/store/helpers/entity-factory.ts index aa59cf8ae2..240b2986f9 100644 --- a/src/frontend/app/store/helpers/entity-factory.ts +++ b/src/frontend/app/store/helpers/entity-factory.ts @@ -3,8 +3,6 @@ import { Schema, schema } from 'normalizr'; import { getAPIResourceGuid } from '../selectors/api.selectors'; import { APIResource } from '../types/api.types'; import { CfUser, CfUserRoleParams, OrgUserRoleNames, SpaceUserRoleNames } from '../types/user.types'; -import { ExtensionService } from '../../core/extension/extension-service'; -import { registerAPIRequestEntity } from '../reducers/api-request-reducers.generator'; export const applicationSchemaKey = 'application'; export const stackSchemaKey = 'stack'; @@ -36,6 +34,8 @@ export const metricSchemaKey = 'metrics'; export const userProfileSchemaKey = 'userProfile'; export const servicePlanVisibilitySchemaKey = 'servicePlanVisibility'; export const serviceBrokerSchemaKey = 'serviceBroker'; +export const userFavoritesSchemaKey = 'userFavorites'; + export const spaceWithOrgKey = 'spaceWithOrg'; export const serviceInstancesWithSpaceSchemaKey = 'serviceInstancesWithSpace'; export const serviceInstancesWithNoBindingsSchemaKey = 'serviceInstanceWithNoBindings'; @@ -311,8 +311,8 @@ const ServicePlanVisibilitySchema = new EntitySchema(servicePlanVisibilitySchema }, { idAttribute: getAPIResourceGuid }); entityCache[servicePlanVisibilitySchemaKey] = ServicePlanVisibilitySchema; -const ServiceBrokerSchema = new EntitySchema(serviceBrokerSchemaKey, {}, { idAttribute: getAPIResourceGuid }); -entityCache[serviceBrokerSchemaKey] = ServiceBrokerSchema; +const UserFavoritesSchemaKey = new EntitySchema(userFavoritesSchemaKey, {}, { idAttribute: getAPIResourceGuid }); +entityCache[userFavoritesSchemaKey] = UserFavoritesSchemaKey; const ApplicationEntitySchema = new EntitySchema( applicationSchemaKey, @@ -353,6 +353,9 @@ const orgUserEntity = { } }; +const ServiceBrokerSchema = new EntitySchema(serviceBrokerSchemaKey, {}, { idAttribute: getAPIResourceGuid }); +entityCache[serviceBrokerSchemaKey] = ServiceBrokerSchema; + function createUserOrgSpaceSchema(schemaKey, entity, relationKey): EntitySchema { return new EntitySchema(schemaKey, entity, { idAttribute: getAPIResourceGuid }, relationKey); } diff --git a/src/frontend/app/store/reducers.module.ts b/src/frontend/app/store/reducers.module.ts index cea40585ee..63d1437e10 100644 --- a/src/frontend/app/store/reducers.module.ts +++ b/src/frontend/app/store/reducers.module.ts @@ -1,5 +1,6 @@ +import { TruncatePipe } from './../core/truncate.pipe'; import { NgModule } from '@angular/core'; -import { StoreModule, ActionReducerMap } from '@ngrx/store'; +import { StoreModule, ActionReducerMap, ActionReducer } from '@ngrx/store'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { storeFreeze } from 'ngrx-store-freeze'; import { storeLogger } from 'ngrx-store-logger'; @@ -20,6 +21,8 @@ import { requestPaginationReducer } from './reducers/pagination-reducer.generato import { routingReducer } from './reducers/routing.reducer'; import { uaaSetupReducer } from './reducers/uaa-setup.reducers'; import { UsersRolesReducer } from './reducers/users-roles.reducer'; +import { userFavoriteGroupsReducer } from './reducers/current-user-roles-reducer/user-favorites-groups.reducer'; +import { recentlyVisitedReducer } from './reducers/current-user-roles-reducer/recently-visited.reducer'; export function logger(reducer) { // default, no options @@ -43,15 +46,18 @@ export const appReducers = { manageUsersRoles: UsersRolesReducer, internalEvents: internalEventReducer, currentUserRoles: currentUserRolesReducer, + userFavoritesGroups: userFavoriteGroupsReducer, + recentlyVisited: recentlyVisitedReducer } as ActionReducerMap<{}>; -let metaReducers = []; +const metaReducers = []; if (!environment.production) { - metaReducers = [storeFreeze]; + metaReducers.push(storeFreeze); if (environment.logEnableConsoleActions) { metaReducers.push(logger); } } + const store = StoreModule.forRoot( appReducers, { diff --git a/src/frontend/app/store/reducers/api-request-reducers.generator.ts b/src/frontend/app/store/reducers/api-request-reducers.generator.ts index 725a866bb4..a38a0f475e 100644 --- a/src/frontend/app/store/reducers/api-request-reducers.generator.ts +++ b/src/frontend/app/store/reducers/api-request-reducers.generator.ts @@ -25,6 +25,7 @@ import { spaceQuotaSchemaKey, spaceSchemaKey, userProfileSchemaKey, + userFavoritesSchemaKey, } from '../helpers/entity-factory'; import { endpointStoreNames } from '../types/endpoint.types'; import { RequestTypes } from './../actions/request.actions'; @@ -40,6 +41,9 @@ import { serviceInstanceReducer } from './service-instance.reducer'; import { systemEndpointsReducer } from './system-endpoints.reducer'; import { userReducer, userSpaceOrgReducer, endpointDisconnectUserReducer } from './users.reducer'; import { applicationAddRemoveReducer } from './application-add-remove-reducer'; +import { addOrUpdateUserFavoriteMetadataReducer, deleteUserFavoriteMetadataReducer } from './favorite.reducer'; +import { IRequestDataState, IRequestState } from '../types/entity.types'; +import { Action } from '@ngrx/store'; /** * This module uses the request data reducer and request reducer factories to create @@ -109,13 +113,14 @@ const entities = [ userProfileSchemaKey, servicePlanVisibilitySchemaKey, serviceBrokerSchemaKey, + userFavoritesSchemaKey ]; export function registerAPIRequestEntity(schemaKey: string) { entities.push(schemaKey); } -export function requestReducer(state, action) { +export function requestReducer(state: IRequestState, action: Action) { const baseRequestReducer = requestReducerFactory(entities, requestActions); const extraReducers = { [appStatsSchemaKey]: [appStatsReducer] @@ -123,7 +128,7 @@ export function requestReducer(state, action) { return chainReducers(baseRequestReducer, extraReducers)(state, action); } -export function requestDataReducer(state, action) { +export function requestDataReducer(state: IRequestDataState, action: Action) { const baseDataReducer = requestDataReducerFactory(entities, requestActions); const extraReducers = { @@ -145,6 +150,10 @@ export function requestDataReducer(state, action) { updateOrganizationSpaceReducer(), endpointDisconnectApplicationReducer(), userSpaceOrgReducer(false) + ], + [userFavoritesSchemaKey]: [ + addOrUpdateUserFavoriteMetadataReducer, + deleteUserFavoriteMetadataReducer ] }; diff --git a/src/frontend/app/store/reducers/current-user-roles-reducer/recently-visited.reducer.helpers.ts b/src/frontend/app/store/reducers/current-user-roles-reducer/recently-visited.reducer.helpers.ts new file mode 100644 index 0000000000..74359aeade --- /dev/null +++ b/src/frontend/app/store/reducers/current-user-roles-reducer/recently-visited.reducer.helpers.ts @@ -0,0 +1,118 @@ +import { + IRecentlyVisitedState, + IEntityHit, + IRecentlyVisitedEntities, + IRecentlyVisitedEntityDated, + IRecentlyVisitedEntity +} from '../../types/recently-visited.types'; +import { AddRecentlyVisitedEntityAction } from '../../actions/recently-visited.actions'; + +const MAX_RECENT_COUNT = 100; + +function getEntities(entities: IRecentlyVisitedEntities, newHit: IEntityHit, recentlyVisited: IRecentlyVisitedEntityDated) { + if (!entities[newHit.guid]) { + return { + ...entities, + [newHit.guid]: recentlyVisited + }; + } + return entities; +} + +function trimRecent(hits: IEntityHit[]) { + if (shouldTrim(hits)) { + return hits.slice(0, MAX_RECENT_COUNT - 1); + } + return hits; +} + +function shouldTrim(hits: IEntityHit[]) { + return hits.length >= MAX_RECENT_COUNT; +} + +const endpointIdIsInList = () => { + const recentCache = {}; + return (recent: IRecentlyVisitedEntity, endpointGuids: string[]) => { + const { endpointId } = recent; + const cached = recentCache[endpointId]; + if (cached === true || cached === false) { + return cached; + } + recentCache[endpointId] = endpointGuids.includes(recent.endpointId); + return recentCache[endpointId]; + }; +}; + + +const idExistsInEntityList = (id: string, recents: IRecentlyVisitedEntities) => { + return !!recents[id]; +}; + +export const getDefaultRecentState = () => ({ + entities: {}, + hits: [] +}); + +export function addNewHit(state: IRecentlyVisitedState, action: AddRecentlyVisitedEntityAction): IRecentlyVisitedState { + const entities = state.entities; + const newHit = { + guid: action.recentlyVisited.guid, + date: action.recentlyVisited.date + } as IEntityHit; + const hits = [ + newHit, + ...trimRecent(state.hits), + ]; + const newEntities = getEntities(entities, newHit, action.recentlyVisited); + const newState = { + entities: newEntities, + hits + }; + return shouldTrim(state.hits) ? cleanEntities(newState) : newState; +} + +export function cleanRecentsList(state: IRecentlyVisitedState, endpointGuids?: string[], inclusive = false): IRecentlyVisitedState { + const isInList = endpointIdIsInList(); + if (!endpointGuids) { + return state; + } + if (!endpointGuids.length) { + return inclusive ? getDefaultRecentState() : state; + } + const entities = Object.keys(state.entities).reduce((reducedRecents, currentRecentGuid) => { + const currentRecent = state.entities[currentRecentGuid]; + const inList = isInList(currentRecent, endpointGuids); + if ( + (!inList && !inclusive) || + (inList && inclusive) + ) { + reducedRecents[currentRecentGuid] = currentRecent; + } + return reducedRecents; + }, {}); + const hits = state.hits.reduce((reducedHits, hit) => { + if (idExistsInEntityList(hit.guid, entities)) { + reducedHits.push(hit); + } + return reducedHits; + }, []); + return { + entities, + hits + }; +} + +export function cleanEntities(state: IRecentlyVisitedState) { + const entities = Object.keys(state.entities).reduce((reducedRecents, currentRecentGuid) => { + const currentRecent = state.entities[currentRecentGuid]; + const hasHit = state.hits.find(hit => hit.guid === currentRecentGuid); + if (hasHit) { + reducedRecents[currentRecentGuid] = currentRecent; + } + return reducedRecents; + }, {}); + return { + entities, + hits: state.hits + }; +} diff --git a/src/frontend/app/store/reducers/current-user-roles-reducer/recently-visited.reducer.ts b/src/frontend/app/store/reducers/current-user-roles-reducer/recently-visited.reducer.ts new file mode 100644 index 0000000000..02339953f7 --- /dev/null +++ b/src/frontend/app/store/reducers/current-user-roles-reducer/recently-visited.reducer.ts @@ -0,0 +1,47 @@ +import { + IRecentlyVisitedState, + +} from '../../types/recently-visited.types'; +import { AddRecentlyVisitedEntityAction, SetRecentlyVisitedEntityAction } from '../../actions/recently-visited.actions'; +import { + DISCONNECT_ENDPOINTS_SUCCESS, + UNREGISTER_ENDPOINTS_SUCCESS, + DisconnectEndpoint, + GetAllEndpointsSuccess, + GET_ENDPOINTS_SUCCESS +} from '../../actions/endpoint.actions'; +import { Action } from '@ngrx/store'; +import { getDefaultRecentState, addNewHit, cleanRecentsList } from './recently-visited.reducer.helpers'; + +export function recentlyVisitedReducer( + state: IRecentlyVisitedState = getDefaultRecentState(), + action: Action +): IRecentlyVisitedState { + switch (action.type) { + case AddRecentlyVisitedEntityAction.ACTION_TYPE: + return addNewHit(state, action as AddRecentlyVisitedEntityAction); + case SetRecentlyVisitedEntityAction.ACTION_TYPE: + const setAction = action as SetRecentlyVisitedEntityAction; + return { + hits: state.hits, + entities: { + ...state.entities, + [setAction.recentlyVisited.guid]: setAction.recentlyVisited + } + }; + case DISCONNECT_ENDPOINTS_SUCCESS: + case UNREGISTER_ENDPOINTS_SUCCESS: + const removeEndpointAction = action as DisconnectEndpoint; + return cleanRecentsList(state, [removeEndpointAction.guid]); + case GET_ENDPOINTS_SUCCESS: + const getAllAction = action as GetAllEndpointsSuccess; + const connectedIds = Object.values(getAllAction.payload.entities.endpoint).reduce((ids, endpoint) => { + if (endpoint.user) { + ids.push(endpoint.guid); + } + return ids; + }, []); + return cleanRecentsList(state, connectedIds, true); + } + return state; +} diff --git a/src/frontend/app/store/reducers/current-user-roles-reducer/user-favorites-groups.reducer.spec.ts b/src/frontend/app/store/reducers/current-user-roles-reducer/user-favorites-groups.reducer.spec.ts new file mode 100644 index 0000000000..60127acef3 --- /dev/null +++ b/src/frontend/app/store/reducers/current-user-roles-reducer/user-favorites-groups.reducer.spec.ts @@ -0,0 +1,277 @@ +import { userFavoriteGroupsReducer } from './user-favorites-groups.reducer'; +import { UserFavorite, IEndpointFavMetadata } from '../../types/user-favorites.types'; +import { SaveUserFavoriteSuccessAction } from '../../actions/user-favourites-actions/save-user-favorite-action'; +import { IUserFavoritesGroupsState, getDefaultFavoriteGroupsState } from '../../types/favorite-groups.types'; +import { deriveEndpointFavoriteFromFavorite } from '../../../core/user-favorite-helpers'; +import { + GetUserFavoritesSuccessAction, + GetUserFavoritesAction, + GetUserFavoritesFailedAction +} from '../../actions/user-favourites-actions/get-user-favorites-action'; +import { RemoveUserFavoriteSuccessAction } from '../../actions/user-favourites-actions/remove-user-favorite-action'; +const endpointFavorite = () => new UserFavorite( + 'endpoint1', + 'cf', + 'endpoint' +); + +const endpointFavorite2 = () => new UserFavorite( + 'endpoint2', + 'cf', + 'endpoint' +); + +const favorite = () => new UserFavorite( + 'endpoint1', + 'cf', + 'application', + 'entity1' +); + +const favorite2 = () => new UserFavorite( + 'endpoint2', + 'cf', + 'application', + 'entity2' +); + +const favorite21 = () => new UserFavorite( + 'endpoint2', + 'cf', + 'application', + 'entity21' +); + +const favorite3 = () => new UserFavorite( + 'endpoint3', + 'cf', + 'application', + 'entity3' +); + +describe('userFavoritesReducer', () => { + it(' [empty state] should add new favorite endpoint', () => { + const endpointFav = endpointFavorite(); + const action = new SaveUserFavoriteSuccessAction(endpointFav); + const newState = userFavoriteGroupsReducer(undefined, action); + const defaultState = getDefaultFavoriteGroupsState(); + expect(newState).toEqual({ + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: false, + search: null, + typeFilter: null, + entitiesIds: [] + } + } + } as IUserFavoritesGroupsState); + }); + + it(' [empty state] should add new entity and mark endpoint group as ethereal', () => { + const fav = favorite(); + const endpointFav = deriveEndpointFavoriteFromFavorite(fav); + const action = new SaveUserFavoriteSuccessAction(fav); + const newState = userFavoriteGroupsReducer(undefined, action); + const defaultState = getDefaultFavoriteGroupsState(); + expect(newState).toEqual({ + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: true, + search: null, + typeFilter: null, + entitiesIds: [ + fav.guid + ] + } + } + } as IUserFavoritesGroupsState); + }); + + it('should add new favorite to none ethereal endpoint group', () => { + const endpointFav = endpointFavorite(); + const fav = favorite(); + const action = new SaveUserFavoriteSuccessAction(fav); + const defaultState = getDefaultFavoriteGroupsState(); + const newState = userFavoriteGroupsReducer( + { + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: false, + search: null, + typeFilter: null, + entitiesIds: [] + } + } + }, + action + ); + + expect(newState).toEqual({ + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: false, + search: null, + typeFilter: null, + entitiesIds: [ + fav.guid + ] + } + } + } as IUserFavoritesGroupsState); + }); + + it('should sort all endpoints into appropriate groups', () => { + const fav = favorite(); + const fav2 = favorite2(); + const endpointFav = endpointFavorite(); + const endpointFav2 = endpointFavorite2(); + const fav21 = favorite21(); + const fav3 = favorite3(); + + const favs = [ + fav, + fav2, + endpointFav, + endpointFav2, + fav21, + fav3 + ]; + + const action = new GetUserFavoritesSuccessAction(favs); + const newState = userFavoriteGroupsReducer(undefined, action); + + const endpoint3Fav = deriveEndpointFavoriteFromFavorite(fav3); + const defaultState = getDefaultFavoriteGroupsState(); + expect(newState).toEqual({ + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: false, + search: null, + typeFilter: null, + entitiesIds: [ + fav.guid + ] + }, + [endpointFav2.guid]: { + ethereal: false, + search: null, + typeFilter: null, + entitiesIds: [ + fav2.guid, + fav21.guid + ] + }, + [endpoint3Fav.guid]: { + ethereal: true, + search: null, + typeFilter: null, + entitiesIds: [ + fav3.guid + ] + } + } + } as IUserFavoritesGroupsState); + }); + + it('should delete new favorite from none ethereal group', () => { + const endpointFav = endpointFavorite(); + const fav = favorite(); + const action = new RemoveUserFavoriteSuccessAction(fav); + const defaultState = getDefaultFavoriteGroupsState(); + const newState = userFavoriteGroupsReducer({ + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: false, + search: null, + typeFilter: null, + entitiesIds: [ + fav.guid + ] + } + } + }, action); + + expect(newState).toEqual({ + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: false, + search: null, + typeFilter: null, + entitiesIds: [ + ] + } + } + } as IUserFavoritesGroupsState); + }); + + it('should delete new favorite from ethereal group', () => { + const endpointFav = endpointFavorite(); + const fav = favorite(); + const action = new RemoveUserFavoriteSuccessAction(fav); + const defaultState = getDefaultFavoriteGroupsState(); + const newState = userFavoriteGroupsReducer({ + ...defaultState, + groups: { + [endpointFav.guid]: { + ethereal: true, + search: null, + typeFilter: null, + entitiesIds: [ + fav.guid + ] + } + } + }, action); + expect(newState).toEqual({ + ...defaultState, + groups: {} + } as IUserFavoritesGroupsState); + }); + + it('should set fetching to true', () => { + const action = new GetUserFavoritesAction(); + const defaultState = getDefaultFavoriteGroupsState(); + const newState = userFavoriteGroupsReducer(undefined, action); + expect(newState).toEqual({ + ...defaultState, + busy: true + } as IUserFavoritesGroupsState); + }); + + it('should set fetching to false', () => { + const action = new GetUserFavoritesSuccessAction([]); + const defaultState = getDefaultFavoriteGroupsState(); + const newState = userFavoriteGroupsReducer({ + ...defaultState, + busy: true + }, action); + expect(newState).toEqual({ + ...defaultState, + busy: false + } as IUserFavoritesGroupsState); + }); + + it('should set error to true', () => { + const action = new GetUserFavoritesFailedAction(); + const defaultState = getDefaultFavoriteGroupsState(); + const newState = userFavoriteGroupsReducer({ + ...defaultState, + busy: true, + error: false + }, action); + expect(newState).toEqual({ + ...defaultState, + busy: false, + error: true, + message: 'Failed to fetch favorites' + } as IUserFavoritesGroupsState); + }); +}); + diff --git a/src/frontend/app/store/reducers/current-user-roles-reducer/user-favorites-groups.reducer.ts b/src/frontend/app/store/reducers/current-user-roles-reducer/user-favorites-groups.reducer.ts new file mode 100644 index 0000000000..4e48ac0197 --- /dev/null +++ b/src/frontend/app/store/reducers/current-user-roles-reducer/user-favorites-groups.reducer.ts @@ -0,0 +1,140 @@ +import { + IUserFavoritesGroupsState, + getDefaultFavoriteGroup, + IUserFavoriteGroup, + getDefaultFavoriteGroupsState, + IUserFavoritesGroups +} from '../../types/favorite-groups.types'; +import { Action } from '@ngrx/store'; +import { + GetUserFavoritesSuccessAction, + GetUserFavoritesAction, + GetUserFavoritesFailedAction +} from '../../actions/user-favourites-actions/get-user-favorites-action'; +import { RemoveUserFavoriteSuccessAction } from '../../actions/user-favourites-actions/remove-user-favorite-action'; +import { SaveUserFavoriteSuccessAction } from '../../actions/user-favourites-actions/save-user-favorite-action'; +import { isEndpointTypeFavorite, deriveEndpointFavoriteFromFavorite } from '../../../core/user-favorite-helpers'; +import { UserFavorite, IFavoriteMetadata } from '../../types/user-favorites.types'; + +export function userFavoriteGroupsReducer( + state: IUserFavoritesGroupsState = getDefaultFavoriteGroupsState(), + action: Action +): IUserFavoritesGroupsState { + switch (action.type) { + case GetUserFavoritesAction.ACTION_TYPE: + return { + ...state, + busy: true, + error: false, + message: '' + }; + case GetUserFavoritesSuccessAction.ACTION_TYPE: + return { + ...state, + busy: false, + error: false, + message: '', + groups: buildFavoritesGroups(action as GetUserFavoritesSuccessAction) + }; + case GetUserFavoritesFailedAction.ACTION_TYPE: + return { + ...state, + busy: false, + error: true, + message: 'Failed to fetch favorites', + }; + case RemoveUserFavoriteSuccessAction.ACTION_TYPE: + return { + ...state, + groups: removeFavoriteFromGroup(state.groups, action as RemoveUserFavoriteSuccessAction) + }; + case SaveUserFavoriteSuccessAction.ACTION_TYPE: + return { + ...state, + groups: addEntityFavorite(state.groups, action as SaveUserFavoriteSuccessAction) + }; + } + return state; +} + +function buildFavoritesGroups(action: GetUserFavoritesSuccessAction) { + const { favorites } = action; + return favorites.reduce((favoriteGroups, favorite) => { + const { guid } = deriveEndpointFavoriteFromFavorite(favorite); + favoriteGroups[guid] = addFavoriteToGroup(favoriteGroups[guid], favorite); + return favoriteGroups; + }, {} as IUserFavoritesGroups); +} + +function removeFavoriteFromGroup(state: IUserFavoritesGroups, action: RemoveUserFavoriteSuccessAction): IUserFavoritesGroups { + const { favorite } = action; + const endpointFavorite = deriveEndpointFavoriteFromFavorite(favorite); + const userGroup = state[endpointFavorite.guid] || getDefaultFavoriteGroup(); + if (isEndpointTypeFavorite(favorite)) { + if (!groupHasEntities(userGroup)) { + return removeGroup(state, endpointFavorite.guid); + } + // The endpoint has been removed but dependant entities are still within the group + // The group is now ethereal + return { + ...state, + [endpointFavorite.guid]: { + ...userGroup, + ethereal: true + } + }; + } else { + const entitiesIds = userGroup.entitiesIds.filter(id => id !== favorite.guid); + if (!entitiesIds.length && userGroup.ethereal) { + return removeGroup(state, endpointFavorite.guid); + } + return { + ...state, + [endpointFavorite.guid]: { + ...userGroup, + entitiesIds + } + }; + } +} + +function removeGroup(state: IUserFavoritesGroups, endpointGuid: string): IUserFavoritesGroups { + const { + [endpointGuid]: removedEndpoint, + ...newState + } = state; + return newState; +} + +function groupHasEntities(group: IUserFavoriteGroup) { + return group.entitiesIds.length > 0; +} + +function addEntityFavorite(favoriteGroups: IUserFavoritesGroups, action: SaveUserFavoriteSuccessAction): IUserFavoritesGroups { + const { favorite } = action; + const { guid } = deriveEndpointFavoriteFromFavorite(favorite); + const group = favoriteGroups[guid]; + const newGroup = addFavoriteToGroup(group, favorite); + return { + ...favoriteGroups, + [guid]: newGroup + }; +} + +function addFavoriteToGroup(_favoriteGroup: IUserFavoriteGroup = getDefaultFavoriteGroup(), favorite: UserFavorite) { + const favoriteGroup = { + ..._favoriteGroup, + entitiesIds: [ + ..._favoriteGroup.entitiesIds + ] + }; + const { guid } = favorite; + const isEndpoint = isEndpointTypeFavorite(favorite); + if (!isEndpoint && guid && !favoriteGroup.entitiesIds.includes(guid)) { + favoriteGroup.entitiesIds.push(guid); + } + if (isEndpoint) { + favoriteGroup.ethereal = false; + } + return favoriteGroup; +} diff --git a/src/frontend/app/store/reducers/favorite.reducer.ts b/src/frontend/app/store/reducers/favorite.reducer.ts new file mode 100644 index 0000000000..fb32e91696 --- /dev/null +++ b/src/frontend/app/store/reducers/favorite.reducer.ts @@ -0,0 +1,37 @@ +import { IRequestEntityTypeState } from '../app-state'; + +import { UserFavorite, IFavoriteMetadata } from '../types/user-favorites.types'; + +import { UpdateUserFavoriteMetadataSuccessAction } from '../actions/user-favourites-actions/update-user-favorite-metadata-action'; +import { RemoveUserFavoriteSuccessAction } from '../actions/user-favourites-actions/remove-user-favorite-action'; +import { SaveUserFavoriteSuccessAction } from '../actions/user-favourites-actions/save-user-favorite-action'; + +export function addOrUpdateUserFavoriteMetadataReducer( + state: IRequestEntityTypeState>, + action: UpdateUserFavoriteMetadataSuccessAction +): IRequestEntityTypeState> { + if ( + action.type === UpdateUserFavoriteMetadataSuccessAction.ACTION_TYPE || + action.type === SaveUserFavoriteSuccessAction.ACTION_TYPE + ) { + return { + ...state, + [action.favorite.guid]: action.favorite + }; + } + return state; +} +export function deleteUserFavoriteMetadataReducer( + state: IRequestEntityTypeState>, + action: RemoveUserFavoriteSuccessAction +): IRequestEntityTypeState> { + if (action.type === RemoveUserFavoriteSuccessAction.ACTION_TYPE) { + const { + [action.favorite.guid]: deletedFavorite, + ...newState + } = state; + return newState; + } + return state; +} + diff --git a/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-reset-pagination.ts b/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-reset-pagination.ts index 303e7ef863..f17953e858 100644 --- a/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-reset-pagination.ts +++ b/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-reset-pagination.ts @@ -1,5 +1,6 @@ +import { PaginationEntityState } from './../../types/pagination.types'; import { PaginationState } from '../../types/pagination.types'; -export function paginationResetPagination(state: PaginationState, action) { +export function paginationResetPagination(state: PaginationState, action): PaginationState { if (!state[action.entityKey] || !state[action.entityKey][action.paginationKey]) { return state; } @@ -10,13 +11,10 @@ export function paginationResetPagination(state: PaginationState, action) { ...newState[action.entityKey][action.paginationKey], ids: {}, pageRequests: {}, - fetching: false, pageCount: 0, currentPage: 1, - totalResults: 0, - error: false, - message: '' - } + totalResults: 0 + } as PaginationEntityState }; return { ...newState, diff --git a/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-success.ts b/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-success.ts index 79345540ef..33708b5bad 100644 --- a/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-success.ts +++ b/src/frontend/app/store/reducers/pagination-reducer/pagination-reducer-success.ts @@ -6,7 +6,7 @@ export function paginationSuccess(state: PaginationEntityState, action): Paginat totalResults = totalResults || (response ? response.result.length : state.totalResults); totalPages = totalPages || (response ? response.totalPages : state.pageCount); const page = apiAction.pageNumber || state.currentPage; - const pageResult = result || (response ? response.result : state[page]); + const pageResult = result || (response ? response.result : state.ids[page]); return { ...state, diff --git a/src/frontend/app/store/selectors/favorite-groups.selectors.ts b/src/frontend/app/store/selectors/favorite-groups.selectors.ts new file mode 100644 index 0000000000..d9547d13c7 --- /dev/null +++ b/src/frontend/app/store/selectors/favorite-groups.selectors.ts @@ -0,0 +1,60 @@ +import { AppState, IRequestEntityTypeState } from '../app-state'; +import { IUserFavoritesGroups, IUserFavoritesGroupsState, IUserFavoriteGroup } from '../types/favorite-groups.types'; +import { UserFavorite, IFavoriteMetadata } from '../types/user-favorites.types'; +import { deriveEndpointFavoriteFromFavorite } from '../../core/user-favorite-helpers'; +import { compose } from '@ngrx/store'; + + +export const favoriteEntitiesSelector = (state: AppState): + IRequestEntityTypeState> => state.requestData.userFavorites; + + +export const favoriteGroupsStateSelector = (state: AppState): IUserFavoritesGroupsState => state.userFavoritesGroups; + +export const favoriteGroupsFetchingSelector = (state: IUserFavoritesGroupsState): boolean => state.busy; + +export const favoriteGroupsErrorSelector = (state: IUserFavoritesGroupsState): boolean => state.error; + +export const favoriteGroupsSelector = compose( + (state: IUserFavoritesGroupsState): IUserFavoritesGroups => state.groups, + favoriteGroupsStateSelector +); + + +export const favoriteGroupSelector = (favorite: UserFavorite) => { + const endpointFavorite = deriveEndpointFavoriteFromFavorite(favorite); + return (groups: IUserFavoritesGroups): IUserFavoriteGroup => { + return groups[endpointFavorite.guid]; + }; +}; + +export const favoriteInGroupGroupSelector = (favorite: UserFavorite) => { + return (group: IUserFavoriteGroup): boolean => { + if (!group) { + return false; + } + if (favorite.entityType === 'endpoint' && !group.ethereal) { + return true; + } + return group.entitiesIds.includes(favorite.guid); + }; +}; + +export function isFavoriteSelector(favorite: UserFavorite) { + return compose( + favoriteInGroupGroupSelector(favorite), + favoriteGroupSelector(favorite), + favoriteGroupsSelector + ); +} + +export const fetchingFavoritesSelector = compose( + favoriteGroupsFetchingSelector, + favoriteGroupsStateSelector +); + +export const errorFetchingFavoritesSelector = compose( + favoriteGroupsErrorSelector, + favoriteGroupsStateSelector +); + diff --git a/src/frontend/app/store/selectors/favorite.selectors.ts b/src/frontend/app/store/selectors/favorite.selectors.ts new file mode 100644 index 0000000000..351e646241 --- /dev/null +++ b/src/frontend/app/store/selectors/favorite.selectors.ts @@ -0,0 +1,9 @@ +import { IFavoriteMetadata, UserFavorite } from '../types/user-favorites.types'; +import { isFavoriteSelector } from './favorite-groups.selectors'; +export function isFavorite(favorite: UserFavorite) { + if (!favorite) { + return () => false; + } + return isFavoriteSelector(favorite); +} + diff --git a/src/frontend/app/store/selectors/pagination.selectors.ts b/src/frontend/app/store/selectors/pagination.selectors.ts index 15be92acd2..82d11ed551 100644 --- a/src/frontend/app/store/selectors/pagination.selectors.ts +++ b/src/frontend/app/store/selectors/pagination.selectors.ts @@ -1,12 +1,41 @@ -import { AppState } from '../app-state'; -import { PaginationEntityTypeState, PaginationState } from '../types/pagination.types'; import { compose } from '@ngrx/store'; -export function selectPaginationState(entityKey: string, paginationKey: string) { +import { AppState } from '../app-state'; +import { PaginationEntityTypeState } from '../types/pagination.types'; +import { PaginationEntityState, PaginationState } from './../types/pagination.types'; + +export function isIdInPagination(entityId: string, entityKey: string, paginationKey: string) { return compose( + checkPagesForId(entityId), + selectPaginationState(entityKey, paginationKey) + ); +} + +export function selectPaginationState(entityKey: string, paginationKey: string) { + const state = compose( getPaginationKeyState(paginationKey), getPaginationEntityState(entityKey), getPaginationState ); + return state; +} + +export function checkPagesForId(entityId: string) { + return (paginationState: PaginationEntityState) => { + if (!paginationState) { + return false; + } + return !!Object.keys(paginationState.ids).reduce((flatPages, pageId) => { + const page = paginationState.ids[pageId]; + if (page && Array.isArray(page)) { + return [ + ...flatPages, + ...paginationState.ids[pageId] + ]; + } + return flatPages; + }, []) + .find((id => id === entityId)); + }; } export function getPaginationKeyState(paginationKey: string) { diff --git a/src/frontend/app/store/selectors/recently-visitied.selectors.ts b/src/frontend/app/store/selectors/recently-visitied.selectors.ts new file mode 100644 index 0000000000..0a6f280d7a --- /dev/null +++ b/src/frontend/app/store/selectors/recently-visitied.selectors.ts @@ -0,0 +1,2 @@ +import { AppState } from './../app-state'; +export const recentlyVisitedSelector = (state: AppState) => state.recentlyVisited; diff --git a/src/frontend/app/store/store.module.ts b/src/frontend/app/store/store.module.ts index fe5f0fd212..06de709eed 100644 --- a/src/frontend/app/store/store.module.ts +++ b/src/frontend/app/store/store.module.ts @@ -29,6 +29,7 @@ import { UserProfileEffect } from './effects/user-profile.effects'; import { UsersRolesEffects } from './effects/users-roles.effects'; import { UsersEffects } from './effects/users.effects'; import { AppReducersModule } from './reducers.module'; +import { UserFavoritesEffect } from './effects/user-favorites-effect'; import { EndpointApiError } from './effects/endpoint-api-errors.effects'; import { AppStoreExtensionsModule } from './store.extensions.module'; @@ -66,6 +67,7 @@ import { AppStoreExtensionsModule } from './store.extensions.module'; RecursiveDeleteEffect, AppEffects, RouteEffect, + UserFavoritesEffect ]) ] }) diff --git a/src/frontend/app/store/types/api.types.ts b/src/frontend/app/store/types/api.types.ts index 91041f5708..f38936561e 100644 --- a/src/frontend/app/store/types/api.types.ts +++ b/src/frontend/app/store/types/api.types.ts @@ -11,6 +11,14 @@ export interface APIResource { metadata: APIResourceMetadata; entity: T; } + +export interface CfAPIResource extends APIResource { + entity: { + [entityKey: string]: any, + cfGuid: string + }; +} + export function instanceOfAPIResource(object: any): boolean { return object && typeof object === 'object' && 'metadata' in object && 'entity' in object; } @@ -22,8 +30,8 @@ export interface APIResourceMetadata { url: string; } -export interface NormalizedResponse { - entities: IRequestEntityTypeState; +export interface NormalizedResponse { + entities: IRequestEntityTypeState<{ [entityKey: string]: T }>; result: string[]; } diff --git a/src/frontend/app/store/types/endpoint.types.ts b/src/frontend/app/store/types/endpoint.types.ts index ef9609c50a..7bd47663dc 100644 --- a/src/frontend/app/store/types/endpoint.types.ts +++ b/src/frontend/app/store/types/endpoint.types.ts @@ -4,6 +4,7 @@ import { endpointSchemaKey } from '../helpers/entity-factory'; import { RequestSectionKeys, TRequestTypeKeys } from '../reducers/api-request-reducer/types'; import { EndpointType } from '../../core/extension/extension-types'; +export const endpointListKey = 'endpoint-list'; export interface INewlyConnectedEndpointInfo { account: string; admin: boolean; diff --git a/src/frontend/app/store/types/entity.types.ts b/src/frontend/app/store/types/entity.types.ts index d8e26dafb9..36ee479b3d 100644 --- a/src/frontend/app/store/types/entity.types.ts +++ b/src/frontend/app/store/types/entity.types.ts @@ -35,6 +35,7 @@ import { spaceQuotaSchemaKey, spaceSchemaKey, stackSchemaKey, + userFavoritesSchemaKey, } from '../helpers/entity-factory'; import { RequestInfoState } from '../reducers/api-request-reducer/types'; import { APIResource } from './api.types'; @@ -42,6 +43,7 @@ import { IMetrics } from './base-metric.types'; import { EndpointModel } from './endpoint.types'; import { GitBranch, GitCommit } from './git.types'; import { SystemInfo } from './system.types'; +import { UserFavorite, IFavoriteMetadata } from './user-favorites.types'; import { CfUser } from './user.types'; export interface IRequestDataState extends IRequestTypeState { @@ -66,6 +68,7 @@ export interface IRequestDataState extends IRequestTypeState { servicePlanVisibility: IRequestEntityTypeState>; serviceBroker: IRequestEntityTypeState>; metrics: IRequestEntityTypeState; + userFavorites: IRequestEntityTypeState>; // Extensibility [name: string]: IRequestEntityTypeState; } @@ -91,6 +94,7 @@ export interface IRequestState extends IRequestTypeState { securityGroup: IRequestEntityTypeState; servicePlanVisibility: IRequestEntityTypeState; serviceBroker: IRequestEntityTypeState; + userFavorites: IRequestEntityTypeState; // Extensibility [name: string]: IRequestEntityTypeState; } @@ -122,5 +126,6 @@ export const defaultCfEntitiesState = { [spaceQuotaSchemaKey]: {}, [metricSchemaKey]: {}, [servicePlanVisibilitySchemaKey]: {}, - [serviceBrokerSchemaKey]: {} + [serviceBrokerSchemaKey]: {}, + [userFavoritesSchemaKey]: {} }; diff --git a/src/frontend/app/store/types/favorite-groups.types.ts b/src/frontend/app/store/types/favorite-groups.types.ts new file mode 100644 index 0000000000..b9c445357b --- /dev/null +++ b/src/frontend/app/store/types/favorite-groups.types.ts @@ -0,0 +1,31 @@ +import { ActionState } from '../reducers/api-request-reducer/types'; + +export interface IUserFavoritesGroupsState extends ActionState { + groups: IUserFavoritesGroups; +} +export interface IUserFavoritesGroups { + [endpointGuid: string]: IUserFavoriteGroup; +} + + +export interface IUserFavoriteGroup { + // Did we automatically add the endpoint to the group? + ethereal: boolean; + search: string; + typeFilter: string; + entitiesIds: string[]; +} + +export const getDefaultFavoriteGroup = (): IUserFavoriteGroup => ({ + ethereal: true, + search: null, + typeFilter: null, + entitiesIds: [] +}); + +export const getDefaultFavoriteGroupsState = (): IUserFavoritesGroupsState => ({ + busy: false, + error: false, + message: '', + groups: {} +}); diff --git a/src/frontend/app/store/types/recently-visited.types.ts b/src/frontend/app/store/types/recently-visited.types.ts new file mode 100644 index 0000000000..d9f8e12b56 --- /dev/null +++ b/src/frontend/app/store/types/recently-visited.types.ts @@ -0,0 +1,27 @@ +import { IFavoriteTypeInfo } from './user-favorites.types'; + +export interface IEntityHit { + guid: string; + date: number; +} +export interface IRecentlyVisitedEntity extends IFavoriteTypeInfo { + guid: string; + name: string; + entityId: string; + prettyType: string; + prettyEndpointType: string; + endpointId: string; + routerLink?: string; +} + +export interface IRecentlyVisitedEntities { + [guid: string]: IRecentlyVisitedEntity; +} +export interface IRecentlyVisitedState { + entities: IRecentlyVisitedEntities; + hits: IEntityHit[]; +} + +export interface IRecentlyVisitedEntityDated extends IRecentlyVisitedEntity { + date: number; +} diff --git a/src/frontend/app/store/types/request.types.ts b/src/frontend/app/store/types/request.types.ts index 1deac391b7..2277871652 100644 --- a/src/frontend/app/store/types/request.types.ts +++ b/src/frontend/app/store/types/request.types.ts @@ -125,9 +125,9 @@ export class StartRequestAction extends RequestAction { } } -export class WrapperRequestActionSuccess extends RequestSuccessAction implements ISuccessRequestAction { +export class WrapperRequestActionSuccess extends RequestSuccessAction implements ISuccessRequestAction { constructor( - public response: NormalizedResponse, + public response: NormalizedResponse, public apiAction: IRequestAction | PaginatedAction, public requestType: ApiRequestTypes = 'fetch', public totalResults?: number, diff --git a/src/frontend/app/store/types/user-favorites.types.ts b/src/frontend/app/store/types/user-favorites.types.ts new file mode 100644 index 0000000000..61d705ada5 --- /dev/null +++ b/src/frontend/app/store/types/user-favorites.types.ts @@ -0,0 +1,100 @@ +import { endpointSchemaKey } from '../helpers/entity-factory'; +import { favoritesConfigMapper } from '../../shared/components/favorites-meta-card/favorite-config-mapper'; +import { EndpointModel } from './endpoint.types'; + +export const userFavoritesPaginationKey = 'userFavorites'; + +/** + * A user favorite blueprint. Can be used to fetch the full entity from a particular endpoint. + */ +export interface IFavoriteTypeInfo { + endpointType: string; + entityType: string; +} + +export interface IFavoriteMetadata { + [key: string]: string; +} +export interface IEndpointFavMetadata extends IFavoriteMetadata { + guid: string; + address: string; + user: string; + admin: string; +} + +// Metadata is a json string when stored in the backend so we use this interface to +// represent what is store in the backend. +export interface BackendUserFavorite { + entityId: string; + endpointId: string; + entityType: string; + endpointType: string; + metadata: string; +} + +const favoriteGuidSeparator = '-'; + +export class UserFavorite implements IFavoriteTypeInfo { + public guid: string; + public metadata: T = null; + constructor( + public endpointId: string, + public endpointType: string, + /* + entityType should correspond to a type in the requestData part of the store. + */ + public entityType: string, + public entityId?: string, + entity?: Y, + ) { + if (entity) { + this.metadata = favoritesConfigMapper.getEntityMetadata(this, entity); + } + this.guid = UserFavorite.buildFavoriteStoreEntityGuid(this); + } + + static buildFavoriteStoreEntityGuid(favorite: UserFavorite) { + const { + entityId, + endpointId, + entityType, + endpointType, + } = favorite; + return [ + entityId, + endpointId, + entityType, + endpointType, + ] + .reduce((newArray, value) => { + if (value) { + return [ + ...newArray, + value, + ]; + } + return newArray; + }, []) + .join(favoriteGuidSeparator); + } + + static getEntityGuidFromFavoriteGuid(favoriteGuid: string) { + return favoriteGuid.split(favoriteGuidSeparator)[0]; + } +} + +export class UserFavoriteEndpoint extends UserFavorite { + constructor( + public endpointId: string, + public endpointType: string, + endpoint: EndpointModel + ) { + super( + endpointId, + endpointType, + endpointSchemaKey, + null, + endpoint + ); + } +} diff --git a/src/frontend/app/test-framework/store-test-helper.ts b/src/frontend/app/test-framework/store-test-helper.ts index 6b389731f0..c15643e606 100644 --- a/src/frontend/app/test-framework/store-test-helper.ts +++ b/src/frontend/app/test-framework/store-test-helper.ts @@ -29,6 +29,16 @@ export function getInitialTestStoreState(): AppState { function getDefaultInitialTestStoreState(): AppState { return { + recentlyVisited: { + entities: {}, + hits: [] + }, + userFavoritesGroups: { + busy: false, + error: false, + message: '', + groups: {} + }, auth: { loggedIn: true, loggingIn: false, @@ -299,6 +309,7 @@ function getDefaultInitialTestStoreState(): AppState { }, stack: {}, space: {}, + userFavorites: {}, organization: { endpointOrgSpaceService: { pageCount: 1, @@ -650,6 +661,7 @@ function getDefaultInitialTestStoreState(): AppState { featureFlag: {}, securityRule: {}, buildpack: {}, + userFavorites: {}, user: { 'bcf78136-6225-4515-bf8e-a32243deea0c': { fetching: false, @@ -3897,6 +3909,7 @@ function getDefaultInitialTestStoreState(): AppState { space_quota_definition: {}, }, requestData: { + userFavorites: {}, servicePlanVisibility: {}, serviceBroker: { 'a55f1a04-e3a3-4a89-92ee-94e3f96103f3': { diff --git a/src/jetstream/cnsi.go b/src/jetstream/cnsi.go index cccf50fdd9..407d9126d7 100644 --- a/src/jetstream/cnsi.go +++ b/src/jetstream/cnsi.go @@ -15,6 +15,7 @@ import ( "crypto/sha1" "encoding/base64" + "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/userfavorites/userfavoritesendpoints" "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/cnsis" "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/tokens" @@ -148,11 +149,14 @@ func (p *portalProxy) unregisterCluster(c echo.Context) error { "Missing target endpoint", "Need CNSI GUID passed as form param") } - + // Should check for errors? p.unsetCNSIRecord(cnsiGUID) p.unsetCNSITokenRecords(cnsiGUID) + ufe := userfavoritesendpoints.Constructor(p, cnsiGUID) + ufe.RemoveFavorites() + return nil } diff --git a/src/jetstream/datastore/20181129140500_UserFavorites.go b/src/jetstream/datastore/20181129140500_UserFavorites.go new file mode 100644 index 0000000000..6707d57e70 --- /dev/null +++ b/src/jetstream/datastore/20181129140500_UserFavorites.go @@ -0,0 +1,36 @@ +package datastore + +import ( + "database/sql" + + "bitbucket.org/liamstask/goose/lib/goose" +) + +func init() { + RegisterMigration(20181129140500, "UserFavorites", func(txn *sql.Tx, conf *goose.DBConf) error { + + createFavoritesTable := "CREATE TABLE IF NOT EXISTS favorites (" + createFavoritesTable += "guid VARCHAR(255) NOT NULL," + createFavoritesTable += "user_guid VARCHAR(36) NOT NULL," + createFavoritesTable += "endpoint_type VARCHAR(16) NOT NULL," + createFavoritesTable += "endpoint_id VARCHAR(255) NOT NULL," + createFavoritesTable += "entity_type VARCHAR(255) NOT NULL," + createFavoritesTable += "entity_id VARCHAR(255)," + createFavoritesTable += "metadata TEXT," + createFavoritesTable += "last_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP," + createFavoritesTable += "PRIMARY KEY (guid, user_guid) );" + + _, err := txn.Exec(createFavoritesTable) + if err != nil { + return err + } + + createIndex := "CREATE INDEX favorites_user_guid ON favorites (user_guid);" + _, err = txn.Exec(createIndex) + if err != nil { + return err + } + + return nil + }) +} diff --git a/src/jetstream/default.config.properties b/src/jetstream/default.config.properties index d03c95f23a..dbbdde92a7 100644 --- a/src/jetstream/default.config.properties +++ b/src/jetstream/default.config.properties @@ -5,10 +5,10 @@ HTTP_CLIENT_TIMEOUT_IN_SECS=30 HTTP_CLIENT_TIMEOUT_MUTATING_IN_SECS=120 SKIP_SSL_VALIDATION=true CONSOLE_PROXY_TLS_ADDRESS=:5443 -CONSOLE_CLIENT=cf +CONSOLE_CLIENT=console CF_CLIENT=cf UAA_ENDPOINT=http://localhost:8080 -CONSOLE_ADMIN_SCOPE=cloud_controller.admin +CONSOLE_ADMIN_SCOPE=stratos.admin CF_ADMIN_ROLE=cloud_controller.admin ALLOWED_ORIGINS=http://nginx SESSION_STORE_SECRET=wheeee! diff --git a/src/jetstream/load_plugins.go b/src/jetstream/load_plugins.go index 6d8c5c907a..fd2ad0e3e8 100644 --- a/src/jetstream/load_plugins.go +++ b/src/jetstream/load_plugins.go @@ -6,6 +6,7 @@ import ( "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/cloudfoundry" "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/cloudfoundryhosting" "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/metrics" + "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/userfavorites" "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/userinfo" "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" log "github.com/sirupsen/logrus" @@ -27,6 +28,7 @@ func (pp *portalProxy) loadPlugins() { {"cloudfoundryhosting", cloudfoundryhosting.Init}, {"metrics", metrics.Init}, {"userinfo", userinfo.Init}, + {"userfavorites", userfavorites.Init}, } { plugin, err := p.Init(pp) pp.Plugins[p.Name] = plugin diff --git a/src/jetstream/main.go b/src/jetstream/main.go index a5be126f6b..7b562d54c1 100644 --- a/src/jetstream/main.go +++ b/src/jetstream/main.go @@ -235,6 +235,12 @@ func main() { log.Info("Unable to start Stratos JetStream backend") } + +// GetDatabaseConnection makes db connection available to plugins +func (portalProxy *portalProxy) GetDatabaseConnection() *sql.DB { + return portalProxy.DatabaseConnectionPool +} + func initialiseConsoleConfiguration(portalProxy *portalProxy) (*setupMiddleware, error) { addSetupMiddleware := new(setupMiddleware) diff --git a/src/jetstream/plugins/userfavorites/favorites.go b/src/jetstream/plugins/userfavorites/favorites.go new file mode 100644 index 0000000000..7d87db1146 --- /dev/null +++ b/src/jetstream/plugins/userfavorites/favorites.go @@ -0,0 +1,192 @@ +package userfavorites + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/http" + "strings" + + "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/userfavorites/userfavoritesstore" + "github.com/labstack/echo" + + "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" +) + +func (uf *UserFavorites) getAll(c echo.Context) error { + + store, err := userfavoritesstore.NewFavoritesDBStore(uf.portalProxy.GetDatabaseConnection()) + if err != nil { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Unable to get favorites store", + "Unable to get favorites store") + } + userGUID := c.Get("user_id").(string) + list, err := store.List(userGUID) + if err != nil { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Unable to get favorites from favorites store", + "Unable to get favorites from favorites store") + } + + jsonString, err := json.Marshal(list) + if err != nil { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Unable Marshal favorites from favorites json", + "Unable Marshal favorites from favorites json") + } + + c.Response().Header().Set("Content-Type", "application/json") + c.Response().Write(jsonString) + return nil +} + +func (uf *UserFavorites) delete(c echo.Context) error { + + store, err := userfavoritesstore.NewFavoritesDBStore(uf.portalProxy.GetDatabaseConnection()) + if err != nil { + return err + } + + favoriteGUID := c.Param("guid") + if len(favoriteGUID) == 0 { + return errors.New("Invalid favorite GUID") + } + + userGUID := c.Get("user_id").(string) + err = store.Delete(userGUID, favoriteGUID) + if err != nil { + return err + } + c.Response().Header().Set("Content-Type", "application/json") + c.Response().Write([]byte("{\"response\": \"User Favorite deleted okay\"}")) + return nil +} + +func (uf *UserFavorites) setMetadata(c echo.Context) error { + + store, err := userfavoritesstore.NewFavoritesDBStore(uf.portalProxy.GetDatabaseConnection()) + if err != nil { + return err + } + + favoriteGUID := c.Param("guid") + if len(favoriteGUID) == 0 { + return errors.New("Invalid favorite GUID") + } + req := c.Request() + body, _ := ioutil.ReadAll(req.Body) + userGUID := c.Get("user_id").(string) + // Unmarshal + var msg map[string]interface{} + err = json.Unmarshal(body, &msg) + if err != nil { + return fmt.Errorf("Unable to un Marshal User Favorite metadata body: %v", err) + } + + metadataBytes, err := json.Marshal(msg) + if err != nil { + return fmt.Errorf("Unable to Marshal User Favorite metadata: %v", err) + } + err = store.SetMetadata(userGUID, favoriteGUID, string(metadataBytes)) + if err != nil { + return err + } + c.Response().Header().Set("Content-Type", "application/json") + c.Response().Write([]byte("{\"response\": \"User Favorite metadata updated okay\"}")) + return nil +} + +func (uf *UserFavorites) create(c echo.Context) error { + + store, err := userfavoritesstore.NewFavoritesDBStore(uf.portalProxy.GetDatabaseConnection()) + if err != nil { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Unable to connect to User Favorite store", + "Unable to connect to User Favorite store") + } + + userGUID := c.Get("user_id").(string) + + req := c.Request() + body, _ := ioutil.ReadAll(req.Body) + + favorite := userfavoritesstore.UserFavoriteRecord{} + err = json.Unmarshal(body, &favorite) + if err != nil { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Unable to parse User Favorite from request body", + "Unable to parse User Favorite from request body") + } + + if len(favorite.EndpointID) == 0 || len(favorite.EndpointType) == 0 { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Invalid request - must provide EndpointID and EndpointType", + "Invalid request - must provide EndpointID and EndpointType") + } + + favorite.GUID = buildFavoriteStoreEntityGuid(favorite) + favorite.UserGUID = userGUID + updatedFavorite, err := store.Save(favorite) + if err != nil { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Failed to save favorite to db", + "Failed to save favorite to db") + } + + jsonString, err := json.Marshal(updatedFavorite) + if err != nil { + return interfaces.NewHTTPShadowError( + http.StatusBadRequest, + "Failed to Marshal favorite from db", + "Failed to Marshal favorite from db") + } + + c.Response().Header().Set("Content-Type", "application/json") + c.Response().Write(jsonString) + return nil +} + +// RemoveEndpointFavorites removes favorites form an endpoint using the given endpoint guid +func (uf *UserFavorites) RemoveEndpointFavorites(endpointGUID string) error { + store, err := userfavoritesstore.NewFavoritesDBStore(uf.portalProxy.GetDatabaseConnection()) + if err != nil { + return err + } + + if len(endpointGUID) == 0 { + return errors.New("Invalid endpoint GUID") + } + + err = store.DeleteFromEndpoint(endpointGUID) + if err != nil { + return err + } + return nil +} + +func buildFavoriteStoreEntityGuid(favorite userfavoritesstore.UserFavoriteRecord) string { + values := []string{} + if len(favorite.EntityID) > 0 { + values = append(values, favorite.EntityID) + } + if len(favorite.EndpointID) > 0 { + values = append(values, favorite.EndpointID) + } + if len(favorite.EntityType) > 0 { + values = append(values, favorite.EntityType) + } + if len(favorite.EndpointType) > 0 { + values = append(values, favorite.EndpointType) + } + + return strings.Join(values, "-") +} diff --git a/src/jetstream/plugins/userfavorites/main.go b/src/jetstream/plugins/userfavorites/main.go new file mode 100644 index 0000000000..c7cc320486 --- /dev/null +++ b/src/jetstream/plugins/userfavorites/main.go @@ -0,0 +1,55 @@ +package userfavorites + +import ( + "errors" + + "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/userfavorites/userfavoritesstore" + "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" + "github.com/labstack/echo" +) + +// UserFavorites stores user favorites +type UserFavorites struct { + portalProxy interfaces.PortalProxy +} + +// Init creates a new UserFavorites +func Init(portalProxy interfaces.PortalProxy) (interfaces.StratosPlugin, error) { + userfavoritesstore.InitRepositoryProvider(portalProxy.GetConfig().DatabaseProviderName) + return &UserFavorites{portalProxy: portalProxy}, nil +} + +// GetMiddlewarePlugin gets the middleware plugin for this plugin +func (uf *UserFavorites) GetMiddlewarePlugin() (interfaces.MiddlewarePlugin, error) { + return nil, errors.New("Not implemented") +} + +// GetEndpointPlugin gets the endpoint plugin for this plugin +func (uf *UserFavorites) GetEndpointPlugin() (interfaces.EndpointPlugin, error) { + return nil, errors.New("Not implemented") +} + +// GetRoutePlugin gets the route plugin for this plugin +func (uf *UserFavorites) GetRoutePlugin() (interfaces.RoutePlugin, error) { + return uf, nil +} + +// AddAdminGroupRoutes adds the admin routes for this plugin to the Echo server +func (uf *UserFavorites) AddAdminGroupRoutes(echoGroup *echo.Group) { + // no-op +} + +// AddSessionGroupRoutes adds the session routes for this plugin to the Echo server +func (uf *UserFavorites) AddSessionGroupRoutes(echoGroup *echo.Group) { + + // Add REST API for User Favorites + echoGroup.GET("/favorites", uf.getAll) + echoGroup.DELETE("/favorites/:guid", uf.delete) + echoGroup.POST("/favorites", uf.create) + echoGroup.POST("/favorites/:guid/metadata", uf.setMetadata) +} + +// Init performs plugin initialization +func (uf *UserFavorites) Init() error { + return nil +} diff --git a/src/jetstream/plugins/userfavorites/userfavoritesendpoints/main.go b/src/jetstream/plugins/userfavorites/userfavoritesendpoints/main.go new file mode 100644 index 0000000000..731f7553c1 --- /dev/null +++ b/src/jetstream/plugins/userfavorites/userfavoritesendpoints/main.go @@ -0,0 +1,37 @@ +package userfavoritesendpoints + +import ( + "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/userfavorites/userfavoritesstore" + "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" +) + +type userFavoriteEndpoints struct { + portalProxy interfaces.PortalProxy + endpointGUID string +} + +type userEndpointFavorites interface { + RemoveFavorites() error +} + +func Constructor(portalProxy interfaces.PortalProxy, endpointGUID string) userEndpointFavorites { + ufe := &userFavoriteEndpoints{ + portalProxy: portalProxy, + endpointGUID: endpointGUID, + } + return ufe +} + +// RemoveEndpointFavorites removes favorites form an endpoint using the given endpoint guid +func (ufe *userFavoriteEndpoints) RemoveFavorites() error { + store, err := userfavoritesstore.NewFavoritesDBStore(ufe.portalProxy.GetDatabaseConnection()) + if err != nil { + return err + } + + err = store.DeleteFromEndpoint(ufe.endpointGUID) + if err != nil { + return err + } + return nil +} diff --git a/src/jetstream/plugins/userfavorites/userfavoritesstore/favorites-store-db.go b/src/jetstream/plugins/userfavorites/userfavoritesstore/favorites-store-db.go new file mode 100644 index 0000000000..69b6e972cc --- /dev/null +++ b/src/jetstream/plugins/userfavorites/userfavoritesstore/favorites-store-db.go @@ -0,0 +1,114 @@ +package userfavoritesstore + +import ( + "database/sql" + "encoding/json" + "fmt" + + log "github.com/sirupsen/logrus" + + "github.com/cloudfoundry-incubator/stratos/src/jetstream/datastore" +) + +var ( + getFavorites = `SELECT guid, endpoint_type, endpoint_id, entity_type, entity_id, metadata FROM favorites WHERE user_guid = $1` + deleteFavorite = `DELETE FROM favorites WHERE user_guid = $1 AND guid = $2` + saveFavorite = `INSERT INTO favorites (guid, user_guid, endpoint_type, endpoint_id, entity_type, entity_id, metadata) VALUES ($1, $2, $3, $4, $5, $6, $7)` + setMetadata = `UPDATE favorites SET metadata = $1 WHERE user_guid = $2 AND guid = $3` + deleteEndpointFavorite = `DELETE FROM favorites WHERE endpoint_id = $1` +) + +// InitRepositoryProvider - One time init for the given DB Provider +func InitRepositoryProvider(databaseProvider string) { + // Modify the database statements if needed, for the given database type + getFavorites = datastore.ModifySQLStatement(getFavorites, databaseProvider) + deleteFavorite = datastore.ModifySQLStatement(deleteFavorite, databaseProvider) + saveFavorite = datastore.ModifySQLStatement(saveFavorite, databaseProvider) +} + +// FavoritesDBStore is a DB-backed User Favorites repository +type FavoritesDBStore struct { + db *sql.DB +} + +// NewFavoritesDBStore will create a new instance of the FavoritesDBStore +func NewFavoritesDBStore(dcp *sql.DB) (FavoritesStore, error) { + return &FavoritesDBStore{db: dcp}, nil +} + +// List - Returns a list of all user favorites +func (p *FavoritesDBStore) List(userGUID string) ([]*UserFavoriteRecord, error) { + log.Debug("List") + rows, err := p.db.Query(getFavorites, userGUID) + if err != nil { + return nil, fmt.Errorf("Unable to retrieve User Favorite records: %v", err) + } + defer rows.Close() + + var favoritesList []*UserFavoriteRecord + favoritesList = make([]*UserFavoriteRecord, 0) + + for rows.Next() { + favorite := new(UserFavoriteRecord) + var metaString sql.NullString + err := rows.Scan(&favorite.GUID, &favorite.EndpointType, &favorite.EndpointID, &favorite.EntityType, &favorite.EntityID, &metaString) + if err != nil { + return nil, fmt.Errorf("Unable to scan User Favorite records: %v", err) + } + + var metadata map[string]interface{} + err = json.Unmarshal([]byte(metaString.String), &metadata) + if err != nil { + return nil, fmt.Errorf("Unable to Marshal User Favorite metadata: %v", err) + } + favorite.Metadata = metadata + + favoritesList = append(favoritesList, favorite) + } + + if err = rows.Err(); err != nil { + return nil, fmt.Errorf("Unable to List User Favorite records: %v", err) + } + + return favoritesList, nil +} + +// Delete will delete a User Favorite from the datastore +func (p *FavoritesDBStore) Delete(userGUID string, guid string) error { + if _, err := p.db.Exec(deleteFavorite, userGUID, guid); err != nil { + return fmt.Errorf("Unable to delete User Favorite record: %v", err) + } + + return nil +} + +// SetMetadata will set the metadata for a User Favorite from the datastore +func (p *FavoritesDBStore) SetMetadata(userGUID string, guid string, metadata string) error { + if _, err := p.db.Exec(setMetadata, metadata, userGUID, guid); err != nil { + return fmt.Errorf("Unable to set metadata on User Favorite record: %v", err) + } + return nil +} + +// Save will persist a User Favorite to a datastore +func (p *FavoritesDBStore) Save(favoriteRecord UserFavoriteRecord) (*UserFavoriteRecord, error) { + + metaString, err := json.Marshal(favoriteRecord.Metadata) + + if err != nil { + return nil, fmt.Errorf("Unable to marshal User Favorite metadata: %v", err) + } + if _, err := p.db.Exec(saveFavorite, favoriteRecord.GUID, favoriteRecord.UserGUID, favoriteRecord.EndpointType, favoriteRecord.EndpointID, favoriteRecord.EntityType, favoriteRecord.EntityID, metaString); err != nil { + return nil, fmt.Errorf("Unable to save User Favorite record: %v", err) + } + + return &favoriteRecord, nil +} + +// DeleteFromEndpoint will remove all favorites for a given endpoint guid +func (p *FavoritesDBStore) DeleteFromEndpoint(endpointGUID string) error { + if _, err := p.db.Exec(deleteEndpointFavorite, endpointGUID); err != nil { + return fmt.Errorf("Unable to User Favorite record: %v", err) + } + return nil +} diff --git a/src/jetstream/plugins/userfavorites/userfavoritesstore/main.go b/src/jetstream/plugins/userfavorites/userfavoritesstore/main.go new file mode 100644 index 0000000000..71ab82577a --- /dev/null +++ b/src/jetstream/plugins/userfavorites/userfavoritesstore/main.go @@ -0,0 +1,20 @@ +package userfavoritesstore + +type UserFavoriteRecord struct { + GUID string `json:"guid"` + UserGUID string `json:"-"` + EndpointType string `json:"endpointType"` + EndpointID string `json:"endpointId"` + EntityType string `json:"entityType"` + EntityID string `json:"entityId"` + Metadata map[string]interface{} `json:"metadata"` +} + +// FavoritesStore is the user favorites repository +type FavoritesStore interface { + List(userGUID string) ([]*UserFavoriteRecord, error) + Delete(userGUID string, guid string) error + Save(favoriteRecord UserFavoriteRecord) (*UserFavoriteRecord, error) + SetMetadata(userGUID string, guid string, metadata string) error + DeleteFromEndpoint(endpointGUID string) error +} diff --git a/src/jetstream/repository/interfaces/portal_proxy.go b/src/jetstream/repository/interfaces/portal_proxy.go index c3767537f2..c1d783fe8b 100644 --- a/src/jetstream/repository/interfaces/portal_proxy.go +++ b/src/jetstream/repository/interfaces/portal_proxy.go @@ -1,6 +1,7 @@ package interfaces import ( + "database/sql" "net/http" "net/url" @@ -58,6 +59,8 @@ type PortalProxy interface { DoProxySingleRequest(cnsiGUID, userGUID, method, requestUrl string) (*CNSIRequest, error) SendProxiedResponse(c echo.Context, responses map[string]*CNSIRequest) error + // Database Connection + GetDatabaseConnection() *sql.DB AddAuthProvider(name string, provider AuthProvider) GetAuthProvider(name string) AuthProvider DoAuthFlowRequest(cnsiRequest *CNSIRequest, req *http.Request, authHandler AuthHandlerFunc) (*http.Response, error) diff --git a/src/test-e2e/dashboard/dashboard-e2e.spec.ts b/src/test-e2e/dashboard/dashboard-e2e.spec.ts deleted file mode 100644 index d1cbf583de..0000000000 --- a/src/test-e2e/dashboard/dashboard-e2e.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { DashboardPage } from './dashboard.po'; -import { E2EHelpers, ConsoleUserType } from '../helpers/e2e-helpers'; -import { browser } from 'protractor'; - -// Dashboard page not implemented -xdescribe('Dashboard', () => { - const helpers = new E2EHelpers(); - const dashboardPage = new DashboardPage(); - - beforeAll(() => { - helpers.setupApp(ConsoleUserType.admin); - }); - - beforeEach(() => { - dashboardPage.navigateTo(); - }); - - it('- should reach dashboard page', () => { - expect(dashboardPage.isDashboardPage()).toBeTruthy(); - }); -}); diff --git a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts index fb93de1b25..5acb529589 100644 --- a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts @@ -8,6 +8,7 @@ import { MenuComponent } from '../po/menu.po'; import { SnackBarComponent } from '../po/snackbar.po'; import { ConnectDialogComponent } from './connect-dialog.po'; import { EndpointMetadata, EndpointsPage } from './endpoints.po'; +import { HomePage } from '../home/home.po'; describe('Endpoints', () => { const endpointsPage = new EndpointsPage(); @@ -106,15 +107,15 @@ describe('Endpoints', () => { expect(endpointsPage.isActivePage()).toBeTruthy(); }); - it('should go directly to applications view on logout and login', () => { + it('should go directly to home page view on logout and login', () => { endpointsPage.header.logout(); const loginPage = new LoginPage(); loginPage.waitForLogin(); loginPage.login(e2e.secrets.getConsoleNonAdminUsername(), e2e.secrets.getConsoleNonAdminPassword()); loginPage.waitForLoading(); loginPage.waitForApplicationPage(); - const appPage = new ApplicationsPage(); - expect(appPage.isActivePage()).toBeTruthy(); + const homePage = new HomePage(); + expect(homePage.isActivePage()).toBeTruthy(); }); }); diff --git a/src/test-e2e/endpoints/endpoints.po.ts b/src/test-e2e/endpoints/endpoints.po.ts index 60a6594d56..a39d2cbda7 100644 --- a/src/test-e2e/endpoints/endpoints.po.ts +++ b/src/test-e2e/endpoints/endpoints.po.ts @@ -1,5 +1,6 @@ import { browser, by, element } from 'protractor'; import { ElementFinder } from 'protractor/built'; + import { E2EEndpointConfig } from '../e2e.types'; import { ConsoleUserType, E2EHelpers } from '../helpers/e2e-helpers'; import { ListComponent, ListTableComponent } from '../po/list.po'; @@ -21,7 +22,8 @@ export class EndpointsTable extends ListTableComponent { type: data[2], user: data[3], isAdmin: data[4].indexOf('Yes') !== -1, - url: data[5] + url: data[5], + favorite: data[6] } as EndpointMetadata; }); } diff --git a/src/test-e2e/home/home-e2e.spec.ts b/src/test-e2e/home/home-e2e.spec.ts new file mode 100644 index 0000000000..1a4e2b6aaf --- /dev/null +++ b/src/test-e2e/home/home-e2e.spec.ts @@ -0,0 +1,22 @@ +import { e2e } from '../e2e'; +import { ConsoleUserType } from '../helpers/e2e-helpers'; +import { HomePage } from './home.po'; + +describe('Home', () => { + const dashboardPage = new HomePage(); + + beforeAll(() => { + e2e.setup(ConsoleUserType.user) + .clearAllEndpoints() + .registerDefaultCloudFoundry() + .connectAllEndpoints(ConsoleUserType.user); + }); + + beforeEach(() => { + dashboardPage.navigateTo(); + }); + + it('- should reach home page', () => { + expect(dashboardPage.isActivePage()).toBeTruthy(); + }); +}); diff --git a/src/test-e2e/dashboard/dashboard.po.ts b/src/test-e2e/home/home.po.ts similarity index 61% rename from src/test-e2e/dashboard/dashboard.po.ts rename to src/test-e2e/home/home.po.ts index bd34986cdc..ad3b602181 100644 --- a/src/test-e2e/dashboard/dashboard.po.ts +++ b/src/test-e2e/home/home.po.ts @@ -1,17 +1,17 @@ -import { protractor } from 'protractor/built'; + import { E2EHelpers } from '../helpers/e2e-helpers'; import { browser, promise } from 'protractor'; +import { Page } from '../po/page.po'; -export class DashboardPage { +export class HomePage extends Page { helpers = new E2EHelpers(); - - navigateTo() { - return browser.get('/dashboard'); + constructor() { + super('/home'); } isDashboardPage(strictCheck: boolean = true): promise.Promise { return browser.getCurrentUrl().then(url => { - return url === browser.baseUrl + '/dashboard' || (strictCheck && url === browser.baseUrl + '/'); + return url === browser.baseUrl + this.navLink || (strictCheck && url === browser.baseUrl + '/'); }); }