Fix after review

This commit is contained in:
Kostya Struga 2022-07-14 15:34:15 +03:00
parent bbcd726d7d
commit 7ef0798332
13 changed files with 631 additions and 133 deletions

View File

@ -28,6 +28,22 @@
"scripts": []
},
"configurations": {
"development": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.ts"
}
]
},
"production": {
"fileReplacements": [
{
@ -65,6 +81,9 @@
"configurations": {
"production": {
"browserTarget": "fraudbusters-ui:build:production"
},
"development": {
"browserTarget": "fraudbusters-ui:build:development"
}
}
},

430
package-lock.json generated
View File

@ -47,6 +47,7 @@
"@angular-eslint/template-parser": "^13.1.0",
"@angular/cli": "^13.0.1",
"@angular/compiler-cli": "^13.0.1",
"@sentry/webpack-plugin": "^1.18.9",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
@ -2874,6 +2875,167 @@
"yarn": ">= 1.13.0"
}
},
"node_modules/@sentry/cli": {
"version": "1.74.4",
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.74.4.tgz",
"integrity": "sha512-BMfzYiedbModsNBJlKeBOLVYUtwSi99LJ8gxxE4Bp5N8hyjNIN0WVrozAVZ27mqzAuy6151Za3dpmOLO86YlGw==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"https-proxy-agent": "^5.0.0",
"mkdirp": "^0.5.5",
"node-fetch": "^2.6.7",
"npmlog": "^4.1.2",
"progress": "^2.0.3",
"proxy-from-env": "^1.1.0",
"which": "^2.0.2"
},
"bin": {
"sentry-cli": "bin/sentry-cli"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@sentry/cli/node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@sentry/cli/node_modules/aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true
},
"node_modules/@sentry/cli/node_modules/are-we-there-yet": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
"dev": true,
"dependencies": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
"node_modules/@sentry/cli/node_modules/gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
"dev": true,
"dependencies": {
"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"
}
},
"node_modules/@sentry/cli/node_modules/is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
"dev": true,
"dependencies": {
"number-is-nan": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@sentry/cli/node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/@sentry/cli/node_modules/npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true,
"dependencies": {
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
"gauge": "~2.7.3",
"set-blocking": "~2.0.0"
}
},
"node_modules/@sentry/cli/node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
"dependencies": {
"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"
}
},
"node_modules/@sentry/cli/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/@sentry/cli/node_modules/string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==",
"dev": true,
"dependencies": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@sentry/cli/node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dev": true,
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@sentry/webpack-plugin": {
"version": "1.18.9",
"resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.18.9.tgz",
"integrity": "sha512-+TrenJrgFM0QTOwBnw0ZXWMvc0PiOebp6GN5EbGEx3JPCQqXOfXFzCaEjBtASKRgcNCL7zGly41S25YR6Hm+jw==",
"dev": true,
"dependencies": {
"@sentry/cli": "^1.74.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@ -4875,6 +5037,15 @@
"node": ">=6"
}
},
"node_modules/code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/codelyzer": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz",
@ -11187,6 +11358,26 @@
"dev": true,
"optional": true
},
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dev": true,
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
@ -11714,6 +11905,15 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@ -13014,6 +13214,15 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/promise-inflight": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
@ -13299,6 +13508,12 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"node_modules/prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@ -15303,6 +15518,12 @@
"node": ">=0.8"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"dev": true
},
"node_modules/tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
@ -15916,6 +16137,12 @@
"node": ">=0.8.0"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"dev": true
},
"node_modules/webpack": {
"version": "5.70.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz",
@ -16257,6 +16484,16 @@
"node": ">=0.8.0"
}
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dev": true,
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -18476,6 +18713,144 @@
"jsonc-parser": "3.0.0"
}
},
"@sentry/cli": {
"version": "1.74.4",
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.74.4.tgz",
"integrity": "sha512-BMfzYiedbModsNBJlKeBOLVYUtwSi99LJ8gxxE4Bp5N8hyjNIN0WVrozAVZ27mqzAuy6151Za3dpmOLO86YlGw==",
"dev": true,
"requires": {
"https-proxy-agent": "^5.0.0",
"mkdirp": "^0.5.5",
"node-fetch": "^2.6.7",
"npmlog": "^4.1.2",
"progress": "^2.0.3",
"proxy-from-env": "^1.1.0",
"which": "^2.0.2"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"dev": true
},
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true
},
"are-we-there-yet": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
"dev": true,
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
"dev": true,
"requires": {
"aproba": "^1.0.3",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.0",
"object-assign": "^4.1.0",
"signal-exit": "^3.0.0",
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wide-align": "^1.1.0"
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"requires": {
"minimist": "^1.2.6"
}
},
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true,
"requires": {
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
"gauge": "~2.7.3",
"set-blocking": "~2.0.0"
}
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==",
"dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"@sentry/webpack-plugin": {
"version": "1.18.9",
"resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.18.9.tgz",
"integrity": "sha512-+TrenJrgFM0QTOwBnw0ZXWMvc0PiOebp6GN5EbGEx3JPCQqXOfXFzCaEjBtASKRgcNCL7zGly41S25YR6Hm+jw==",
"dev": true,
"requires": {
"@sentry/cli": "^1.74.4"
}
},
"@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@ -19984,6 +20359,12 @@
"shallow-clone": "^3.0.0"
}
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==",
"dev": true
},
"codelyzer": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz",
@ -24655,6 +25036,15 @@
"dev": true,
"optional": true
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dev": true,
"requires": {
"whatwg-url": "^5.0.0"
}
},
"node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
@ -25070,6 +25460,12 @@
"boolbase": "^1.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==",
"dev": true
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@ -25962,6 +26358,12 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"promise-inflight": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
@ -26191,6 +26593,12 @@
}
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@ -27715,6 +28123,12 @@
"punycode": "^2.1.1"
}
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"dev": true
},
"tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
@ -28169,6 +28583,12 @@
}
}
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"dev": true
},
"webpack": {
"version": "5.70.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz",
@ -28402,6 +28822,16 @@
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
"dev": true
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dev": true,
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -4,6 +4,7 @@
"scripts": {
"ng": "ng",
"start": "ng serve",
"start:dev": "ng serve --configuration development",
"build": "ng build --prod",
"test": "ng test",
"lint-cmd": "eslint \"src/**/*.{ts,js,html}\" --max-warnings 1072",

View File

@ -1,8 +1,9 @@
import { NgModule } from '@angular/core';
import { AnalyticsService } from './analytics.service';
import { RiskSeriesMapperService } from './riskSeriesMapper.service';
@NgModule({
providers: [AnalyticsService],
providers: [AnalyticsService, RiskSeriesMapperService],
})
export class AnalyticsModule {}

View File

@ -13,14 +13,18 @@ import { RatioResponse } from '../../fb-management/swagger-codegen/model/ratioRe
import { SplitRiskScoreCountRatioResponse } from '../../fb-management/swagger-codegen/model/splitRiskScoreCountRatioResponse';
import { FraudResultListSummaryResponse } from '../../fb-management/swagger-codegen/model/fraudResultListSummaryResponse';
import { FraudResultSummary } from '../../fb-management/swagger-codegen/model/fraudResultSummary';
import { ChartData, Series } from '../../../sections/analytics/model/chart-data';
import { RiskScoreOffsetCountRatio } from '../../fb-management/swagger-codegen/model/riskScoreOffsetCountRatio';
import { ChartData } from '../../../sections/analytics/model/chart-data';
import { RiskSeriesMapperService } from './riskSeriesMapper.service';
@Injectable()
export class AnalyticsService {
private readonly fbAnalyticsUrl = `${this.configService.fbManagementEndpoint}/analytics`;
constructor(private http: HttpClient, private configService: ConfigService) {}
constructor(
private http: HttpClient,
private configService: ConfigService,
private riskSeriesMapperService: RiskSeriesMapperService
) {}
getCurrencies(): Observable<string[]> {
return this.http
@ -67,57 +71,13 @@ export class AnalyticsService {
})
.pipe(
map((response: SplitRiskScoreCountRatioResponse) => {
let newVar = {
series: this.mapSeries(response),
return {
series: this.riskSeriesMapperService.mapSeries(response),
} as ChartData;
console.log(newVar);
return newVar;
})
);
}
private mapSeries(response: SplitRiskScoreCountRatioResponse) {
return response.offsetCountRatios.map(
(value) =>
({
name: value.score,
data: value.offsetCountRatio.map((offsetCountRatioValue) => ({
x: this.getX(offsetCountRatioValue.offset, response.splitUnit),
y: offsetCountRatioValue.countRatio,
fillColor: this.getFillColor(value),
})),
} as Series)
);
}
private getFillColor(value: RiskScoreOffsetCountRatio) {
switch (value.score) {
case 'low':
return '#1ab152';
case 'fatal':
return '#cf1c1d';
default:
return '#c4c4c4';
}
}
private getX(value: number, splitUnit: string) {
switch (splitUnit) {
case 'hour':
return new Date(value).getHours() + 1;
case 'month':
return new Date(value).getMonth() + 1;
case 'day':
return new Date(value).getDay() + 1;
default:
return new Date(value).getDay() + 1;
}
}
getDaysInMonth(date: Date) {
return new Date(date.getFullYear(), date.getMonth(), 0);
}
getSummary(paramsRes: SearchBaseAnalyticsParams): Observable<FraudResultSummary[]> {
return this.http
.get(`${this.fbAnalyticsUrl}/fraud-payments/results/summary`, {

View File

@ -0,0 +1,46 @@
import { Injectable } from '@angular/core';
import { SplitRiskScoreCountRatioResponse } from '../../fb-management/swagger-codegen/model/splitRiskScoreCountRatioResponse';
import { Series } from '../../../sections/analytics/model/chart-data';
import { RiskScoreOffsetCountRatio } from '../../fb-management/swagger-codegen/model/riskScoreOffsetCountRatio';
@Injectable()
export class RiskSeriesMapperService {
mapSeries(response: SplitRiskScoreCountRatioResponse) {
return response.offsetCountRatios.map(
(value) =>
({
name: value.score,
data: value.offsetCountRatio.map((offsetCountRatioValue) => ({
x: this.getX(offsetCountRatioValue.offset, response.splitUnit),
y: offsetCountRatioValue.countRatio,
fillColor: this.getFillColor(value),
})),
} as Series)
);
}
private getFillColor(value: RiskScoreOffsetCountRatio) {
switch (value.score) {
case 'low':
return '#1ab152';
case 'fatal':
return '#cf1c1d';
default:
return '#c4c4c4';
}
}
private getX(value: number, splitUnit: string) {
const ADDITIONAL_FOR_FIX_ZERO_START = 1;
switch (splitUnit) {
case 'hour':
return new Date(value).getHours() + ADDITIONAL_FOR_FIX_ZERO_START;
case 'month':
return new Date(value).getMonth() + ADDITIONAL_FOR_FIX_ZERO_START;
case 'day':
return new Date(value).getDay() + ADDITIONAL_FOR_FIX_ZERO_START;
default:
return new Date(value).getDay() + ADDITIONAL_FOR_FIX_ZERO_START;
}
}
}

View File

@ -39,6 +39,8 @@ import { BarChartComponent } from '../../shared/components/charts/bar-chart/bar-
import { BarChartModule } from '../../shared/components/charts';
import { BaseAnalyticsService } from './components/base/services/base-analytics.service';
import { FraudSummaryListModule } from './components/base/components/fraud-summary-list';
import { RiskSeriesMapperService } from '../../api/payments/analytics/riskSeriesMapper.service';
import { BaseAnalyticsUtilService } from './components/base/services/base-analytics-util.service';
@NgModule({
imports: [
@ -75,6 +77,6 @@ import { FraudSummaryListModule } from './components/base/components/fraud-summa
FraudSummaryListModule,
],
declarations: [AnalyticsComponent, BaseAnalyticsComponent, BaseAnalyticsSearchComponent],
providers: [AnalyticsService, BaseAnalyticsService, DatePipe],
providers: [AnalyticsService, RiskSeriesMapperService, BaseAnalyticsService, DatePipe, BaseAnalyticsUtilService],
})
export class AnalyticsModule {}

View File

@ -10,36 +10,36 @@
<div fxLayout="row" fxlayoutgap="10px grid" fxLayoutAlign="space-between center" [fxLayoutGap]="layoutGapM">
<fb-info-card
fxFlex="25"
[headerText]="'Attempted payments'"
[headerText]="ATTEMPTED_PAYMENTS"
[value]="attemptedPayments$"
[type]="'success'"
[type]="SUCCESS_STYLE"
></fb-info-card>
<fb-info-card
fxFlex="25"
[headerText]="'Blocked payments'"
[headerText]="BLOCKED_PAYMENTS"
[value]="blockedPayments$"
[type]="'error'"
[type]="ERROR_STYLE"
></fb-info-card>
<fb-info-card
fxFlex="25"
[headerText]="'Block rates'"
[value]="blockedRates$"
[headerText]="RATIO_OF_BLOCKED"
[value]="ratioOfBlocked$"
[units]="'%'"
[type]="'error'"
[type]="ERROR_STYLE"
></fb-info-card>
<fb-info-card
fxFlex="25"
[headerText]="'Block sum'"
[value]="blockSum$"
[headerText]="BLOCKED_SUM"
[value]="blockedSum$"
[units]="'$'"
[type]="'error'"
[type]="ERROR_STYLE"
></fb-info-card>
</div>
<div fxFlexFill fxLayout="column" fxLayoutAlign="space-between center" [fxLayoutGap]="layoutGapM">
<mat-card fxFlexFill fxLayoutAlign="start">
<mat-card-content fxFlexFill>
<h4>Fraud result rate</h4>
<label>Rate success and blocked operations</label>
<h4>Fraud result ratio</h4>
<label>Ratio success and blocked operations</label>
<fb-bar-chart
*ngIf="chartData$ | async as chartData"
fxFlexFill

View File

@ -3,6 +3,7 @@ import { LAYOUT_GAP_M } from '../../../../tokens';
import { BaseAnalyticsService } from './services/base-analytics.service';
import { ActivatedRoute, Router } from '@angular/router';
import { DatePipe } from '@angular/common';
import { BaseAnalyticsUtilService } from './services/base-analytics-util.service';
@Component({
templateUrl: 'base-analytics.component.html',
@ -11,84 +12,46 @@ import { DatePipe } from '@angular/common';
export class BaseAnalyticsComponent {
private readonly _yyyyMMDdHHMmSs = 'yyyy-MM-dd HH:mm:ss';
SUCCESS_STYLE = 'success';
ERROR_STYLE = 'error';
BLOCKED_SUM = 'Blocked sum';
RATIO_OF_BLOCKED = 'Ratio of blocked';
BLOCKED_PAYMENTS = 'Blocked payments';
ATTEMPTED_PAYMENTS = 'Attempted payments';
colors = ['#1ab152', '#c4c4c4', '#cf1c1d'];
attemptedPayments$ = this.baseAnalyticsService.attemptedPayments$;
blockedPayments$ = this.baseAnalyticsService.blockedPayments$;
blockedRates$ = this.baseAnalyticsService.blockedRates$;
blockSum$ = this.baseAnalyticsService.blockSum$;
ratioOfBlocked$ = this.baseAnalyticsService.ratioOfBlocked$;
blockedSum$ = this.baseAnalyticsService.blockedSum$;
fraudSummary$ = this.baseAnalyticsService.fraudSummary$;
chartData$ = this.baseAnalyticsService.chartDataX$;
inProgress$ = this.baseAnalyticsService.inProgress$;
constructor(
private route: ActivatedRoute,
private router: Router,
private baseAnalyticsService: BaseAnalyticsService,
private baseAnalyticsUtilService: BaseAnalyticsUtilService,
@Inject(LAYOUT_GAP_M) public layoutGapM: string,
protected datepipe: DatePipe
) {}
search($event) {
this.baseAnalyticsService.search({
fromTime: this.datepipe.transform(this.todayFromTime($event.time).toISOString(), this._yyyyMMDdHHMmSs),
toTime: this.datepipe.transform(new Date().toISOString(), this._yyyyMMDdHHMmSs),
currency: $event.type,
merchantId: $event.partyId,
shopId: $event.shopId,
splitUnit: this.getSplitUnitFromTime($event.time),
});
}
todayFromTime(time): Date {
let diffDay = 1;
switch (time) {
case '1 day': {
diffDay = 1;
break;
}
case '1 week': {
diffDay = 7;
break;
}
case 'last month': {
return this.getDaysInCurrentMonth();
}
case 'last year': {
return this.getDaysYear();
}
default: {
diffDay = 1;
break;
}
if ($event.type) {
this.baseAnalyticsService.search({
fromTime: this.datepipe.transform(
this.baseAnalyticsUtilService.todayFromTime($event.time).toISOString(),
this._yyyyMMDdHHMmSs
),
toTime: this.datepipe.transform(new Date().toISOString(), this._yyyyMMDdHHMmSs),
currency: $event.type,
merchantId: $event.partyId,
shopId: $event.shopId,
splitUnit: this.baseAnalyticsUtilService.getSplitUnitFromTime($event.time),
});
}
const now = new Date();
now.setDate(now.getDate() - diffDay);
now.setHours(0, 0, 0, 0);
return now;
}
getSplitUnitFromTime(time): string {
switch (time) {
case '1 day': {
return 'hour';
}
case 'last year': {
return 'month';
}
default: {
return 'day';
}
}
}
getDaysInCurrentMonth() {
return new Date(new Date().getFullYear(), new Date().getMonth(), 0);
}
getDaysYear() {
return new Date(new Date().getFullYear(), 0, 0);
}
}

View File

@ -7,9 +7,9 @@
<mat-form-field appearance="outline">
<input matInput placeholder="shop" formControlName="shopId" autocomplete="false" />
</mat-form-field>
<mat-form-field class="select" appearance="outline">
<mat-select formControlName="type" *ngIf="currencies$ | async as currencies">
<mat-option *ngFor="let name of currencies" value="{{ name }}">{{ name }}</mat-option>
<mat-form-field class="select" appearance="outline" *ngIf="currencies$ | async as currencies">
<mat-select formControlName="type">
<mat-option *ngFor="let name of currencies" [value]="name">{{ name }}</mat-option>
</mat-select>
</mat-form-field>
</div>

View File

@ -0,0 +1,54 @@
import { Injectable } from '@angular/core';
@Injectable()
export class BaseAnalyticsUtilService {
todayFromTime(time): Date {
let diffDay = 1;
switch (time) {
case '1 day': {
diffDay = 1;
break;
}
case '1 week': {
diffDay = 7;
break;
}
case 'last month': {
return this.getDaysInCurrentMonth();
}
case 'last year': {
return this.getDaysYear();
}
default: {
diffDay = 1;
break;
}
}
const now = new Date();
now.setDate(now.getDate() - diffDay);
now.setHours(0, 0, 0, 0);
return now;
}
getSplitUnitFromTime(time): string {
switch (time) {
case '1 day': {
return 'hour';
}
case 'last year': {
return 'month';
}
default: {
return 'day';
}
}
}
private getDaysInCurrentMonth() {
return new Date(new Date().getFullYear(), new Date().getMonth(), 0);
}
private getDaysYear() {
return new Date(new Date().getFullYear(), 0, 0);
}
}

View File

@ -12,8 +12,8 @@ export class BaseAnalyticsService {
currencies$: Observable<string[]>;
attemptedPayments$: Observable<number>;
blockedPayments$: Observable<number>;
blockedRates$: Observable<number>;
blockSum$: Observable<number>;
ratioOfBlocked$: Observable<number>;
blockedSum$: Observable<number>;
fraudSummary$: Observable<FraudResultSummary[]>;
chartDataX$: Observable<ChartData>;
@ -42,12 +42,12 @@ export class BaseAnalyticsService {
filter((r) => !!r),
shareReplay(1)
);
this.blockedRates$ = this.searchParameters$.pipe(
this.ratioOfBlocked$ = this.searchParameters$.pipe(
switchMap((value) => this.analyticsService.getBlockedPaymentsRatio(value)),
filter((r) => !!r),
shareReplay(1)
);
this.blockSum$ = this.searchParameters$.pipe(
this.blockedSum$ = this.searchParameters$.pipe(
switchMap((value) => this.analyticsService.getBlockedPaymentsSum(value)),
filter((r) => !!r),
shareReplay(1)
@ -63,8 +63,8 @@ export class BaseAnalyticsService {
merge(
this.attemptedPayments$,
this.blockedPayments$,
this.blockedRates$,
this.blockSum$,
this.ratioOfBlocked$,
this.blockedSum$,
this.chartDataX$,
this.fraudSummary$
).subscribe((value) => this.finished$.next(value));

22
webpack.extra.js Normal file
View File

@ -0,0 +1,22 @@
const webpack = require('webpack');
const SentryWebpackPlugin = require('@sentry/webpack-plugin');
module.exports = {
plugins: [
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
...(process.env.SENTRY_AUTH_TOKEN
? [
new SentryWebpackPlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: 'vality-dev',
project: 'fraudbusters',
include: './dist',
ignore: ['node_modules', 'webpack.config.js'],
}),
]
: []),
],
};