From a16428f9516839f78b54487ab2d3dc5a3672b3a2 Mon Sep 17 00:00:00 2001 From: Dan Labrecque Date: Wed, 15 Dec 2021 15:23:40 -0500 Subject: [PATCH 01/29] Remove unused dev-dependency https://issues.redhat.com/browse/COST-2172 --- koku-ui-manifest | 53 --------- package.json | 1 - yarn.lock | 300 ++--------------------------------------------- 3 files changed, 7 insertions(+), 347 deletions(-) diff --git a/koku-ui-manifest b/koku-ui-manifest index c5e6c5edb..a65505aee 100644 --- a/koku-ui-manifest +++ b/koku-ui-manifest @@ -137,7 +137,6 @@ mgmt_services/cost-mgmt:koku-ui/@restart/hooks:0.3.27.yarnlock mgmt_services/cost-mgmt:koku-ui/@restart/hooks:0.3.27.yarnlock mgmt_services/cost-mgmt:koku-ui/@scalprum/core:0.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/@scalprum/react-core:0.1.7.yarnlock -mgmt_services/cost-mgmt:koku-ui/@schibstedpl/circuit-breaker-js:0.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@sentry/browser:5.30.0.yarnlock mgmt_services/cost-mgmt:koku-ui/@sentry/core:5.30.0.yarnlock mgmt_services/cost-mgmt:koku-ui/@sentry/hub:5.30.0.yarnlock @@ -274,7 +273,6 @@ mgmt_services/cost-mgmt:koku-ui/agent-base:6.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/aggregate-error:3.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/airbnb-prop-types:2.16.0.yarnlock mgmt_services/cost-mgmt:koku-ui/ajv-keywords:3.5.2.yarnlock -mgmt_services/cost-mgmt:koku-ui/ajv:5.5.2.yarnlock mgmt_services/cost-mgmt:koku-ui/ajv:6.12.6.yarnlock mgmt_services/cost-mgmt:koku-ui/ajv:6.12.6.yarnlock mgmt_services/cost-mgmt:koku-ui/ajv:6.12.6.yarnlock @@ -307,9 +305,6 @@ mgmt_services/cost-mgmt:koku-ui/array.prototype.flat:1.2.5.yarnlock mgmt_services/cost-mgmt:koku-ui/array.prototype.flat:1.2.5.yarnlock mgmt_services/cost-mgmt:koku-ui/array.prototype.flatmap:1.2.5.yarnlock mgmt_services/cost-mgmt:koku-ui/asap:2.0.6.yarnlock -mgmt_services/cost-mgmt:koku-ui/asn1:0.2.4.yarnlock -mgmt_services/cost-mgmt:koku-ui/assert-plus:1.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/assert-plus:1.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/ast-types-flow:0.0.7.yarnlock mgmt_services/cost-mgmt:koku-ui/astral-regex:2.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/async:2.6.3.yarnlock @@ -319,8 +314,6 @@ mgmt_services/cost-mgmt:koku-ui/attr-accept:1.1.3.yarnlock mgmt_services/cost-mgmt:koku-ui/awesome-debounce-promise:2.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/awesome-imperative-promise:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/awesome-only-resolves-last-promise:1.0.3.yarnlock -mgmt_services/cost-mgmt:koku-ui/aws-sign2:0.7.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/aws4:1.11.0.yarnlock mgmt_services/cost-mgmt:koku-ui/axe-core:4.3.3.yarnlock mgmt_services/cost-mgmt:koku-ui/axios:0.22.0.yarnlock mgmt_services/cost-mgmt:koku-ui/axios:0.21.4.yarnlock @@ -335,7 +328,6 @@ mgmt_services/cost-mgmt:koku-ui/babel-preset-jest:27.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/balanced-match:1.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/base64-js:1.5.1.yarnlock mgmt_services/cost-mgmt:koku-ui/batch:0.6.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/bcrypt-pbkdf:1.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/big.js:5.2.2.yarnlock mgmt_services/cost-mgmt:koku-ui/binary-extensions:2.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/bl:4.1.0.yarnlock @@ -364,8 +356,6 @@ mgmt_services/cost-mgmt:koku-ui/camel-case:4.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/camelcase:5.3.1.yarnlock mgmt_services/cost-mgmt:koku-ui/camelcase:6.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/caniuse-lite:1.0.30001265.yarnlock -mgmt_services/cost-mgmt:koku-ui/capitalize:1.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/caseless:0.12.0.yarnlock mgmt_services/cost-mgmt:koku-ui/chalk:2.4.2.yarnlock mgmt_services/cost-mgmt:koku-ui/chalk:2.4.2.yarnlock mgmt_services/cost-mgmt:koku-ui/chalk:4.1.2.yarnlock @@ -393,8 +383,6 @@ mgmt_services/cost-mgmt:koku-ui/cli-spinners:2.6.1.yarnlock mgmt_services/cost-mgmt:koku-ui/cli-width:3.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/cliui:7.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/clone-deep:4.0.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/clone:1.0.3.yarnlock -mgmt_services/cost-mgmt:koku-ui/clone:2.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/clone:1.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/co:4.6.0.yarnlock mgmt_services/cost-mgmt:koku-ui/collect-v8-coverage:1.0.1.yarnlock @@ -405,8 +393,6 @@ mgmt_services/cost-mgmt:koku-ui/color-name:1.1.4.yarnlock mgmt_services/cost-mgmt:koku-ui/colorette:2.0.16.yarnlock mgmt_services/cost-mgmt:koku-ui/colorette:2.0.16.yarnlock mgmt_services/cost-mgmt:koku-ui/combined-stream:1.0.8.yarnlock -mgmt_services/cost-mgmt:koku-ui/combined-stream:1.0.8.yarnlock -mgmt_services/cost-mgmt:koku-ui/combined-stream:1.0.8.yarnlock mgmt_services/cost-mgmt:koku-ui/commander:7.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/commander:7.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/commander:8.2.0.yarnlock @@ -429,7 +415,6 @@ mgmt_services/cost-mgmt:koku-ui/cookie:0.4.0.yarnlock mgmt_services/cost-mgmt:koku-ui/copy-webpack-plugin:9.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/core-js-pure:3.18.2.yarnlock mgmt_services/cost-mgmt:koku-ui/core-js:2.6.12.yarnlock -mgmt_services/cost-mgmt:koku-ui/core-util-is:1.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/core-util-is:1.0.3.yarnlock mgmt_services/cost-mgmt:koku-ui/cross-env:7.0.3.yarnlock mgmt_services/cost-mgmt:koku-ui/cross-spawn:7.0.3.yarnlock @@ -461,7 +446,6 @@ mgmt_services/cost-mgmt:koku-ui/d3-time-format:2.3.0.yarnlock mgmt_services/cost-mgmt:koku-ui/d3-time:1.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/d3-timer:1.0.10.yarnlock mgmt_services/cost-mgmt:koku-ui/damerau-levenshtein:1.0.7.yarnlock -mgmt_services/cost-mgmt:koku-ui/dashdash:1.14.1.yarnlock mgmt_services/cost-mgmt:koku-ui/data-urls:2.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/date-fns:2.25.0.yarnlock mgmt_services/cost-mgmt:koku-ui/date-fns:2.17.0.yarnlock @@ -521,7 +505,6 @@ mgmt_services/cost-mgmt:koku-ui/domutils:2.8.0.yarnlock mgmt_services/cost-mgmt:koku-ui/domutils:2.8.0.yarnlock mgmt_services/cost-mgmt:koku-ui/domutils:2.8.0.yarnlock mgmt_services/cost-mgmt:koku-ui/dot-case:3.0.4.yarnlock -mgmt_services/cost-mgmt:koku-ui/ecc-jsbn:0.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/ecdsa-sig-formatter:1.0.11.yarnlock mgmt_services/cost-mgmt:koku-ui/ee-first:1.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/electron-to-chromium:1.3.865.yarnlock @@ -613,11 +596,7 @@ mgmt_services/cost-mgmt:koku-ui/execa:5.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/exit:0.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/expect:27.2.5.yarnlock mgmt_services/cost-mgmt:koku-ui/express:4.17.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/extend:3.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/external-editor:3.1.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/extsprintf:1.3.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/extsprintf:1.4.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/fast-deep-equal:1.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/fast-deep-equal:3.1.3.yarnlock mgmt_services/cost-mgmt:koku-ui/fast-deep-equal:3.1.3.yarnlock mgmt_services/cost-mgmt:koku-ui/fast-diff:1.2.0.yarnlock @@ -648,9 +627,7 @@ mgmt_services/cost-mgmt:koku-ui/focus-trap:6.2.2.yarnlock mgmt_services/cost-mgmt:koku-ui/follow-redirects:1.14.4.yarnlock mgmt_services/cost-mgmt:koku-ui/follow-redirects:1.14.4.yarnlock mgmt_services/cost-mgmt:koku-ui/follow-redirects:1.14.4.yarnlock -mgmt_services/cost-mgmt:koku-ui/forever-agent:0.6.1.yarnlock mgmt_services/cost-mgmt:koku-ui/form-data:3.0.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/form-data:2.3.3.yarnlock mgmt_services/cost-mgmt:koku-ui/forwarded:0.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/fresh:0.5.2.yarnlock mgmt_services/cost-mgmt:koku-ui/fs-extra:9.1.0.yarnlock @@ -672,7 +649,6 @@ mgmt_services/cost-mgmt:koku-ui/get-package-type:0.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/get-stdin:5.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/get-stream:6.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/get-symbol-description:1.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/getpass:0.1.7.yarnlock mgmt_services/cost-mgmt:koku-ui/git-revision-webpack-plugin:3.0.6.yarnlock mgmt_services/cost-mgmt:koku-ui/glob-parent:5.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/glob-parent:5.1.2.yarnlock @@ -688,15 +664,12 @@ mgmt_services/cost-mgmt:koku-ui/globals:13.11.0.yarnlock mgmt_services/cost-mgmt:koku-ui/globals:13.11.0.yarnlock mgmt_services/cost-mgmt:koku-ui/globby:11.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/globby:11.0.4.yarnlock -mgmt_services/cost-mgmt:koku-ui/good-guy-http:1.14.0.yarnlock mgmt_services/cost-mgmt:koku-ui/graceful-fs:4.2.8.yarnlock mgmt_services/cost-mgmt:koku-ui/graceful-fs:4.2.8.yarnlock mgmt_services/cost-mgmt:koku-ui/graceful-fs:4.2.8.yarnlock mgmt_services/cost-mgmt:koku-ui/graceful-fs:4.2.8.yarnlock mgmt_services/cost-mgmt:koku-ui/graceful-fs:4.2.8.yarnlock mgmt_services/cost-mgmt:koku-ui/handle-thing:2.0.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/har-schema:2.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/har-validator:5.0.3.yarnlock mgmt_services/cost-mgmt:koku-ui/has-bigints:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/has-flag:3.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/has-flag:4.0.0.yarnlock @@ -705,7 +678,6 @@ mgmt_services/cost-mgmt:koku-ui/has-symbols:1.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/has-tostringtag:1.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/has:1.0.3.yarnlock mgmt_services/cost-mgmt:koku-ui/he:1.2.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/he:1.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/history:4.10.1.yarnlock mgmt_services/cost-mgmt:koku-ui/hoist-non-react-statics:3.3.2.yarnlock mgmt_services/cost-mgmt:koku-ui/hoist-non-react-statics:3.3.2.yarnlock @@ -732,7 +704,6 @@ mgmt_services/cost-mgmt:koku-ui/http-parser-js:0.5.3.yarnlock mgmt_services/cost-mgmt:koku-ui/http-proxy-agent:4.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/http-proxy-middleware:2.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/http-proxy:1.18.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/http-signature:1.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/https-proxy-agent:5.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/human-date:1.4.0.yarnlock mgmt_services/cost-mgmt:koku-ui/human-signals:2.1.0.yarnlock @@ -821,7 +792,6 @@ mgmt_services/cost-mgmt:koku-ui/is-subset:0.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/is-symbol:1.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/is-symbol:1.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/is-typedarray:1.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/is-typedarray:1.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/is-unicode-supported:0.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/is-weakref:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/is-wsl:2.2.0.yarnlock @@ -829,7 +799,6 @@ mgmt_services/cost-mgmt:koku-ui/isarray:0.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/isarray:1.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/isexe:2.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/isobject:3.0.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/isstream:0.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/istanbul-lib-coverage:3.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/istanbul-lib-instrument:4.0.3.yarnlock mgmt_services/cost-mgmt:koku-ui/istanbul-lib-instrument:4.0.3.yarnlock @@ -874,27 +843,22 @@ mgmt_services/cost-mgmt:koku-ui/js-file-download:0.4.12.yarnlock mgmt_services/cost-mgmt:koku-ui/js-tokens:4.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/js-tokens:4.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/js-yaml:3.14.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/jsbn:0.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/jsdoc-type-pratt-parser:1.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/jsdoc-type-pratt-parser:1.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/jsdom:16.7.0.yarnlock mgmt_services/cost-mgmt:koku-ui/jsesc:2.5.2.yarnlock mgmt_services/cost-mgmt:koku-ui/json-parse-better-errors:1.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/json-parse-better-errors:1.0.2.yarnlock -mgmt_services/cost-mgmt:koku-ui/json-schema-traverse:0.3.1.yarnlock mgmt_services/cost-mgmt:koku-ui/json-schema-traverse:0.4.1.yarnlock mgmt_services/cost-mgmt:koku-ui/json-schema-traverse:1.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/json-schema:0.2.3.yarnlock mgmt_services/cost-mgmt:koku-ui/json-stable-stringify-without-jsonify:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/json-stable-stringify:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/json-stringify-safe:5.0.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/json-stringify-safe:5.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/json5:2.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/json5:2.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/json5:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/jsonfile:6.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/jsonify:0.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/jsprim:1.4.1.yarnlock mgmt_services/cost-mgmt:koku-ui/jsx-ast-utils:3.2.1.yarnlock mgmt_services/cost-mgmt:koku-ui/jsx-ast-utils:3.2.1.yarnlock mgmt_services/cost-mgmt:koku-ui/jwa:2.0.0.yarnlock @@ -992,7 +956,6 @@ mgmt_services/cost-mgmt:koku-ui/node-forge:0.10.0.yarnlock mgmt_services/cost-mgmt:koku-ui/node-int64:0.4.0.yarnlock mgmt_services/cost-mgmt:koku-ui/node-modules-regexp:1.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/node-releases:1.1.77.yarnlock -mgmt_services/cost-mgmt:koku-ui/nodesi:1.17.0.yarnlock mgmt_services/cost-mgmt:koku-ui/normalize-package-data:2.5.0.yarnlock mgmt_services/cost-mgmt:koku-ui/normalize-path:3.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/normalize-path:3.0.0.yarnlock @@ -1000,7 +963,6 @@ mgmt_services/cost-mgmt:koku-ui/npm-run-path:4.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/nth-check:2.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/null-loader:4.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/nwsapi:2.2.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/oauth-sign:0.8.2.yarnlock mgmt_services/cost-mgmt:koku-ui/object-assign:4.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/object-inspect:1.11.0.yarnlock mgmt_services/cost-mgmt:koku-ui/object-inspect:1.11.0.yarnlock @@ -1109,12 +1071,10 @@ mgmt_services/cost-mgmt:koku-ui/proxy-addr:2.0.7.yarnlock mgmt_services/cost-mgmt:koku-ui/prr:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/psl:1.8.0.yarnlock mgmt_services/cost-mgmt:koku-ui/punycode:1.3.2.yarnlock -mgmt_services/cost-mgmt:koku-ui/punycode:1.4.1.yarnlock mgmt_services/cost-mgmt:koku-ui/punycode:2.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/punycode:2.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/qs:6.7.0.yarnlock mgmt_services/cost-mgmt:koku-ui/qs:6.9.6.yarnlock -mgmt_services/cost-mgmt:koku-ui/qs:6.5.2.yarnlock mgmt_services/cost-mgmt:koku-ui/querystring:0.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/queue-microtask:1.2.3.yarnlock mgmt_services/cost-mgmt:koku-ui/raf:3.4.1.yarnlock @@ -1172,7 +1132,6 @@ mgmt_services/cost-mgmt:koku-ui/regexpp:3.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/regextras:0.8.0.yarnlock mgmt_services/cost-mgmt:koku-ui/relateurl:0.2.7.yarnlock mgmt_services/cost-mgmt:koku-ui/renderkid:2.0.7.yarnlock -mgmt_services/cost-mgmt:koku-ui/request:2.87.0.yarnlock mgmt_services/cost-mgmt:koku-ui/require-directory:2.1.1.yarnlock mgmt_services/cost-mgmt:koku-ui/require-from-string:2.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/requireindex:1.2.0.yarnlock @@ -1203,10 +1162,6 @@ mgmt_services/cost-mgmt:koku-ui/safe-buffer:5.2.1.yarnlock mgmt_services/cost-mgmt:koku-ui/safe-buffer:5.2.1.yarnlock mgmt_services/cost-mgmt:koku-ui/safe-buffer:5.2.1.yarnlock mgmt_services/cost-mgmt:koku-ui/safe-buffer:5.2.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/safe-buffer:5.2.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/safer-buffer:2.1.2.yarnlock -mgmt_services/cost-mgmt:koku-ui/safer-buffer:2.1.2.yarnlock -mgmt_services/cost-mgmt:koku-ui/safer-buffer:2.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/safer-buffer:2.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/sanitize-html:2.5.1.yarnlock mgmt_services/cost-mgmt:koku-ui/sass-loader:11.1.1.yarnlock @@ -1268,7 +1223,6 @@ mgmt_services/cost-mgmt:koku-ui/spdx-license-ids:3.0.10.yarnlock mgmt_services/cost-mgmt:koku-ui/spdy-transport:3.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/spdy:4.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/sprintf-js:1.0.3.yarnlock -mgmt_services/cost-mgmt:koku-ui/sshpk:1.16.1.yarnlock mgmt_services/cost-mgmt:koku-ui/stack-utils:2.0.5.yarnlock mgmt_services/cost-mgmt:koku-ui/statuses:1.5.0.yarnlock mgmt_services/cost-mgmt:koku-ui/statuses:1.5.0.yarnlock @@ -1325,7 +1279,6 @@ mgmt_services/cost-mgmt:koku-ui/to-fast-properties:2.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/to-regex-range:5.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/toidentifier:1.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/tough-cookie:4.0.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/tough-cookie:2.3.4.yarnlock mgmt_services/cost-mgmt:koku-ui/tr46:2.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/ts-jest:26.5.1.yarnlock mgmt_services/cost-mgmt:koku-ui/ts-loader:8.0.17.yarnlock @@ -1341,9 +1294,6 @@ mgmt_services/cost-mgmt:koku-ui/tslib:2.3.1.yarnlock mgmt_services/cost-mgmt:koku-ui/tslib:2.3.1.yarnlock mgmt_services/cost-mgmt:koku-ui/tslib:2.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/tsutils:3.21.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/tunnel-agent:0.6.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/tweetnacl:0.14.5.yarnlock -mgmt_services/cost-mgmt:koku-ui/tweetnacl:0.14.5.yarnlock mgmt_services/cost-mgmt:koku-ui/type-check:0.4.0.yarnlock mgmt_services/cost-mgmt:koku-ui/type-check:0.4.0.yarnlock mgmt_services/cost-mgmt:koku-ui/type-check:0.3.2.yarnlock @@ -1359,7 +1309,6 @@ mgmt_services/cost-mgmt:koku-ui/typescript:4.4.3.yarnlock mgmt_services/cost-mgmt:koku-ui/typescript:4.4.3.yarnlock mgmt_services/cost-mgmt:koku-ui/unbox-primitive:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/uncontrollable:7.2.1.yarnlock -mgmt_services/cost-mgmt:koku-ui/underscore:1.12.1.yarnlock mgmt_services/cost-mgmt:koku-ui/unist-util-stringify-position:2.0.3.yarnlock mgmt_services/cost-mgmt:koku-ui/universalify:0.1.2.yarnlock mgmt_services/cost-mgmt:koku-ui/universalify:2.0.0.yarnlock @@ -1373,14 +1322,12 @@ mgmt_services/cost-mgmt:koku-ui/util-deprecate:1.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/utila:0.4.0.yarnlock mgmt_services/cost-mgmt:koku-ui/utils-merge:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/uuid:3.4.0.yarnlock -mgmt_services/cost-mgmt:koku-ui/uuid:3.4.0.yarnlock mgmt_services/cost-mgmt:koku-ui/v8-compile-cache:2.3.0.yarnlock mgmt_services/cost-mgmt:koku-ui/v8-compile-cache:2.3.0.yarnlock mgmt_services/cost-mgmt:koku-ui/v8-to-istanbul:8.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/validate-npm-package-license:3.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/value-equal:1.0.1.yarnlock mgmt_services/cost-mgmt:koku-ui/vary:1.1.2.yarnlock -mgmt_services/cost-mgmt:koku-ui/verror:1.10.0.yarnlock mgmt_services/cost-mgmt:koku-ui/victory-area:35.11.4.yarnlock mgmt_services/cost-mgmt:koku-ui/victory-axis:35.11.4.yarnlock mgmt_services/cost-mgmt:koku-ui/victory-axis:35.11.4.yarnlock diff --git a/package.json b/package.json index 6b56ea705..2cb6cb9c1 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,6 @@ "jest": "27.2.4", "jws": "^4.0.0", "mini-css-extract-plugin": "^1.3.7", - "nodesi": "^1.16.0", "null-loader": "4.0.1", "prettier": "2.3.2", "rimraf": "^3.0.2", diff --git a/yarn.lock b/yarn.lock index 800176f27..cedf52dd6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -897,11 +897,6 @@ "@scalprum/core" "^0.1.1" lodash "^4.17.0" -"@schibstedpl/circuit-breaker-js@0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@schibstedpl/circuit-breaker-js/-/circuit-breaker-js-0.0.2.tgz#630589cb0ee933c58053aa32d2bdf4104bfae0be" - integrity sha512-82fEbDRVsEAO/XlaFsGb5GKoAMvlfOd/hiNxyPWMvd1ZYJxxHs8hAu4i5Jrlcgpf1sUhhgV53oJSHNwyThsVFQ== - "@sentry/browser@^5.4.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.30.0.tgz#c28f49d551db3172080caef9f18791a7fd39e3b3" @@ -1723,16 +1718,6 @@ ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1910,18 +1895,6 @@ asap@^2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" @@ -1978,16 +1951,6 @@ awesome-only-resolves-last-promise@^1.0.3: dependencies: awesome-imperative-promise "^1.0.1" -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.6.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - axe-core@^4.0.2: version "4.3.3" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.3.tgz#b55cd8e8ddf659fe89b064680e1c6a4dceab0325" @@ -2100,13 +2063,6 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -2273,16 +2229,6 @@ caniuse-lite@^1.0.30001264: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz#0613c9e6c922e422792e6fcefdf9a3afeee4f8c3" integrity sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw== -capitalize@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/capitalize/-/capitalize-1.0.0.tgz#dc802c580aee101929020d2ca14b4ca8a0ae44be" - integrity sha1-3IAsWAruEBkpAg0soUtMqKCuRL4= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -2436,16 +2382,6 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - integrity sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8= - -clone@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - integrity sha1-0hfR6WERjjrJpLi7oyhVU79kfNs= - clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -2490,7 +2426,7 @@ colorette@^2.0.10, colorette@^2.0.14: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.5: +combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -2604,11 +2540,6 @@ core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -2781,13 +2712,6 @@ damerau-levenshtein@^1.0.6: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw== -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -3068,14 +2992,6 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - ecdsa-sig-formatter@1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" @@ -3787,11 +3703,6 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" -extend@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - external-editor@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -3801,21 +3712,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3954,11 +3850,6 @@ follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.4: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -3968,15 +3859,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@~2.3.1: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -4079,13 +3961,6 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - git-revision-webpack-plugin@3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/git-revision-webpack-plugin/-/git-revision-webpack-plugin-3.0.6.tgz#5dd6c6829fae05b405059dea6195b23875d69d4d" @@ -4146,17 +4021,6 @@ globby@^11.0.1, globby@^11.0.3: merge2 "^1.3.0" slash "^3.0.0" -good-guy-http@1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/good-guy-http/-/good-guy-http-1.14.0.tgz#01d495ebd7c9d7ef9df4b50a2186d94878df5d0f" - integrity sha512-QkxYpypxMBVU+YRgbSckOoIi17a3/1JO1PXERHff1NpFdLrFNoAzn6CQ3xuYJ6veQtVMcVoLzxT8Zp0M6p0Jhg== - dependencies: - "@schibstedpl/circuit-breaker-js" "0.0.2" - capitalize "^1.0.0" - clone "2.1.1" - request "2.87.0" - underscore "1.12.1" - graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" @@ -4167,19 +4031,6 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" @@ -4214,7 +4065,7 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -he@1.2.0, he@^1.2.0: +he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -4403,15 +4254,6 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -4814,7 +4656,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -4858,11 +4700,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - istanbul-lib-coverage@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" @@ -5365,11 +5202,6 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - jsdoc-type-pratt-parser@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.0.4.tgz#5750d2d32ffb001866537d3baaedea7cf84c7036" @@ -5423,11 +5255,6 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -5438,11 +5265,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -5455,7 +5277,7 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= @@ -5488,16 +5310,6 @@ jsonify@~0.0.0: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" @@ -5964,15 +5776,6 @@ node-releases@^1.1.77: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== -nodesi@^1.16.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/nodesi/-/nodesi-1.17.0.tgz#8d193e588564a72c0569d92aa7268f4f86e54ec8" - integrity sha512-xDdTZbmzfiDlizkPWP21hKr22ISyZdD7v+mXWohnacubhGzvyO5WQfuxuO202rIXt+sL4aJccrzQjR6dwLwT4g== - dependencies: - clone "1.0.3" - good-guy-http "1.14.0" - he "1.2.0" - normalize-package-data@^2.3.2: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -6015,11 +5818,6 @@ nwsapi@^2.2.0: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== -oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -6601,11 +6399,6 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -6621,11 +6414,6 @@ qs@6.9.6: resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== -qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -6996,32 +6784,6 @@ renderkid@^2.0.6: lodash "^4.17.21" strip-ansi "^3.0.1" -request@2.87.0: - version "2.87.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== - dependencies: - 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" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -7142,12 +6904,12 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0: +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -7453,21 +7215,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - 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" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - stack-utils@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" @@ -7784,13 +7531,6 @@ tough-cookie@^4.0.0: punycode "^2.1.1" universalify "^0.1.2" -tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== - dependencies: - punycode "^1.4.1" - tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -7867,18 +7607,6 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -7958,11 +7686,6 @@ uncontrollable@^7.0.0: invariant "^2.2.4" react-lifecycles-compat "^3.0.4" -underscore@1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" - integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== - unist-util-stringify-position@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" @@ -8015,7 +7738,7 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.1.0, uuid@^3.4.0: +uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -8052,15 +7775,6 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - victory-area@^35.9.0: version "35.11.4" resolved "https://registry.yarnpkg.com/victory-area/-/victory-area-35.11.4.tgz#a8cc8193c72fc91b9cd75f5cfac8c83253a9c42c" From 1d02d230d27aa13b8d0a279511b6ca7b225f83c5 Mon Sep 17 00:00:00 2001 From: Dan Labrecque Date: Thu, 13 Jan 2022 16:09:40 -0500 Subject: [PATCH 02/29] Added account settings API support https://issues.redhat.com/browse/COST-2201 --- src/api/accountSettings.ts | 29 +++++ .../accountSettings/accountSettings.tsx | 119 ++++++++++++++++++ .../views/components/accountSettings/index.ts | 1 + .../accountSettings.test.ts.snap | 9 ++ .../accountSettings/accountSettings.test.ts | 59 +++++++++ .../accountSettings/accountSettingsActions.ts | 37 ++++++ .../accountSettings/accountSettingsCommon.ts | 6 + .../accountSettings/accountSettingsReducer.ts | 66 ++++++++++ .../accountSettingsSelectors.ts | 15 +++ src/store/accountSettings/index.ts | 13 ++ 10 files changed, 354 insertions(+) create mode 100644 src/api/accountSettings.ts create mode 100644 src/pages/views/components/accountSettings/accountSettings.tsx create mode 100644 src/pages/views/components/accountSettings/index.ts create mode 100644 src/store/accountSettings/__snapshots__/accountSettings.test.ts.snap create mode 100644 src/store/accountSettings/accountSettings.test.ts create mode 100644 src/store/accountSettings/accountSettingsActions.ts create mode 100644 src/store/accountSettings/accountSettingsCommon.ts create mode 100644 src/store/accountSettings/accountSettingsReducer.ts create mode 100644 src/store/accountSettings/accountSettingsSelectors.ts create mode 100644 src/store/accountSettings/index.ts diff --git a/src/api/accountSettings.ts b/src/api/accountSettings.ts new file mode 100644 index 000000000..a2d5ce682 --- /dev/null +++ b/src/api/accountSettings.ts @@ -0,0 +1,29 @@ +import axios from 'axios'; + +import { PagedResponse } from './api'; + +// To do: Adjust when account-settings API is available +export interface AccountSettingsData { + code?: string; + description?: string; + name?: string; +} + +export interface AccountSettingsMeta { + count?: string; + ['cost-type']?: string; + currency?: string; +} + +export interface AccountSettings extends PagedResponse {} + +export function fetchAccountSettings() { + const insights = (window as any).insights; + if (insights && insights.chrome && insights.chrome.auth && insights.chrome.auth.getUser) { + return insights.chrome.auth.getUser().then(() => { + return axios.get(`cost-type/`); // To do: Use account-settings API when available + }); + } else { + return axios.get(`cost-type/`); // To do: Use account-settings API when available + } +} diff --git a/src/pages/views/components/accountSettings/accountSettings.tsx b/src/pages/views/components/accountSettings/accountSettings.tsx new file mode 100644 index 000000000..3e96e4e9f --- /dev/null +++ b/src/pages/views/components/accountSettings/accountSettings.tsx @@ -0,0 +1,119 @@ +import { AccountSettings } from 'api/accountSettings'; +import { getUserAccessQuery } from 'api/queries/userAccessQuery'; +import { UserAccess, UserAccessType } from 'api/userAccess'; +import { AxiosError } from 'axios'; +import React from 'react'; +import { injectIntl, WrappedComponentProps } from 'react-intl'; +import { connect } from 'react-redux'; +import { accountSettingsActions, accountSettingsSelectors } from 'store/accountSettings'; +import { createMapStateToProps, FetchStatus } from 'store/common'; +import { allUserAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { CostTypes } from 'utils/localStorage'; + +interface AccountSettingsWrapperOwnProps { + children?: React.ReactNode; +} + +interface AccountSettingsWrapperDispatchProps { + fetchAccountSettings?: typeof accountSettingsActions.fetchAccountSettings; +} + +interface AccountSettingsWrapperStateProps { + accountSettings: AccountSettings; + accountSettingsError: AxiosError; + accountSettingsFetchStatus?: FetchStatus; + userAccess: UserAccess; + userAccessError: AxiosError; + userAccessFetchStatus: FetchStatus; + userAccessQueryString: string; +} + +interface AccountSettingsWrapperState { + costType?: CostTypes; + currency?: string; +} + +type AccountSettingsWrapperProps = AccountSettingsWrapperOwnProps & + AccountSettingsWrapperDispatchProps & + AccountSettingsWrapperStateProps & + WrappedComponentProps; + +class AccountSettingsWrapperBase extends React.Component { + protected defaultState: AccountSettingsWrapperState = { + // TBD... + }; + public state: AccountSettingsWrapperState = { ...this.defaultState }; + + public componentDidMount() { + this.updateAccountSettings(); + } + + public componentDidUpdate(prevProps: AccountSettingsWrapperProps) { + const { accountSettings } = this.props; + + if (prevProps.accountSettings !== accountSettings) { + // To do: Adjust meta properties when account-settings API is available + const costType = accountSettings ? accountSettings.meta['cost-type'] : CostTypes.unblended; + const currency = accountSettings ? accountSettings.meta.currency : 'USD'; + + // Force update to render children + this.setState({ + costType, + currency, + }); + } + } + + private updateAccountSettings = () => { + const { accountSettingsFetchStatus, fetchAccountSettings } = this.props; + + if (accountSettingsFetchStatus !== FetchStatus.inProgress) { + fetchAccountSettings(); + } + }; + + public render() { + const { accountSettingsFetchStatus, children } = this.props; + + if (accountSettingsFetchStatus === FetchStatus.complete) { + return children; + } + return null; + } +} + +const mapStateToProps = createMapStateToProps( + state => { + const accountSettings = accountSettingsSelectors.selectAccountSettings(state); + const accountSettingsError = accountSettingsSelectors.selectAccountSettingsError(state); + const accountSettingsFetchStatus = accountSettingsSelectors.selectAccountSettingsFetchStatus(state); + + const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); + const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); + const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( + state, + UserAccessType.all, + userAccessQueryString + ); + + return { + accountSettings, + accountSettingsError, + accountSettingsFetchStatus, + userAccess, + userAccessError, + userAccessFetchStatus, + userAccessQueryString, + }; + } +); + +const mapDispatchToProps: AccountSettingsWrapperDispatchProps = { + fetchAccountSettings: accountSettingsActions.fetchAccountSettings, +}; + +const CostTypeConnect = connect(mapStateToProps, mapDispatchToProps)(AccountSettingsWrapperBase); +const AccountSettings = injectIntl(CostTypeConnect); + +export { AccountSettings }; diff --git a/src/pages/views/components/accountSettings/index.ts b/src/pages/views/components/accountSettings/index.ts new file mode 100644 index 000000000..b9056001e --- /dev/null +++ b/src/pages/views/components/accountSettings/index.ts @@ -0,0 +1 @@ +export * from './accountSettings'; diff --git a/src/store/accountSettings/__snapshots__/accountSettings.test.ts.snap b/src/store/accountSettings/__snapshots__/accountSettings.test.ts.snap new file mode 100644 index 000000000..66ab1bd23 --- /dev/null +++ b/src/store/accountSettings/__snapshots__/accountSettings.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`default state 1`] = ` +Object { + "byId": Map {}, + "errors": Map {}, + "fetchStatus": Map {}, +} +`; diff --git a/src/store/accountSettings/accountSettings.test.ts b/src/store/accountSettings/accountSettings.test.ts new file mode 100644 index 000000000..dfcb249b1 --- /dev/null +++ b/src/store/accountSettings/accountSettings.test.ts @@ -0,0 +1,59 @@ +jest.mock('api/accountSettings'); + +import { waitFor } from '@testing-library/react'; +import { AccountSettings, fetchAccountSettings } from 'api/accountSettings'; +import { FetchStatus } from 'store/common'; +import { createMockStoreCreator } from 'store/mockStore'; + +import * as actions from './accountSettingsActions'; +import { stateKey } from './accountSettingsCommon'; +import { accountSettingsReducer } from './accountSettingsReducer'; +import * as selectors from './accountSettingsSelectors'; + +const createProdvidersStore = createMockStoreCreator({ + [stateKey]: accountSettingsReducer, +}); + +const fetchAccountSettingsMock = fetchAccountSettings as jest.Mock; + +// To do: Update for new account-settings API -- mimic cost-type API for now +const accountSettingsMock: AccountSettings = { + data: [ + { + code: 'unblended_cost', + description: 'Unblended', + name: 'Usage cost on the day you are charged', + }, + ], +} as any; + +fetchAccountSettingsMock.mockReturnValue(Promise.resolve({ data: accountSettingsMock })); + +jest.spyOn(selectors, 'selectAccountSettingsFetchStatus'); + +test('default state', async () => { + const store = createProdvidersStore(); + expect(selectors.selectAccountSettingsState(store.getState())).toMatchSnapshot(); +}); + +test('fetch account settings success', async () => { + const store = createProdvidersStore(); + store.dispatch(actions.fetchAccountSettings()); + expect(fetchAccountSettingsMock).toBeCalled(); + expect(selectors.selectAccountSettingsFetchStatus(store.getState())).toBe(FetchStatus.inProgress); + await waitFor(() => expect(selectors.selectAccountSettingsFetchStatus).toHaveBeenCalled()); + const finishedState = store.getState(); + expect(selectors.selectAccountSettingsFetchStatus(finishedState)).toBe(FetchStatus.complete); +}); + +test('fetch account settings failure', async () => { + const store = createProdvidersStore(); + const error = Symbol('getAccountSettings error'); + fetchAccountSettingsMock.mockReturnValueOnce(Promise.reject(error)); + store.dispatch(actions.fetchAccountSettings()); + expect(fetchAccountSettingsMock).toBeCalled(); + expect(selectors.selectAccountSettingsFetchStatus(store.getState())).toBe(FetchStatus.inProgress); + await waitFor(() => expect(selectors.selectAccountSettingsFetchStatus).toHaveBeenCalled()); + const finishedState = store.getState(); + expect(selectors.selectAccountSettingsFetchStatus(finishedState)).toBe(FetchStatus.complete); +}); diff --git a/src/store/accountSettings/accountSettingsActions.ts b/src/store/accountSettings/accountSettingsActions.ts new file mode 100644 index 000000000..b6bd245ba --- /dev/null +++ b/src/store/accountSettings/accountSettingsActions.ts @@ -0,0 +1,37 @@ +import { AccountSettings, fetchAccountSettings as apiGetAccountSettings } from 'api/accountSettings'; +import { AxiosError } from 'axios'; +import { createAction } from 'typesafe-actions'; + +import { getReportId } from './accountSettingsCommon'; + +interface AccountSettingsActionMeta { + reportId: string; +} + +export const fetchAccountSettingsRequest = createAction('accountSettings/fetch/request')(); +export const fetchAccountSettingsSuccess = createAction('accountSettings/fetch/success')< + AccountSettings, + AccountSettingsActionMeta +>(); +export const fetchAccountSettingsFailure = createAction('accountSettings/fetch/failure')< + AxiosError, + AccountSettingsActionMeta +>(); + +export function fetchAccountSettings() { + return dispatch => { + const meta: AccountSettingsActionMeta = { + reportId: getReportId(), + }; + + dispatch(fetchAccountSettingsRequest(meta)); + + return apiGetAccountSettings() + .then(res => { + dispatch(fetchAccountSettingsSuccess(res.data, meta)); + }) + .catch(err => { + dispatch(fetchAccountSettingsFailure(err, meta)); + }); + }; +} diff --git a/src/store/accountSettings/accountSettingsCommon.ts b/src/store/accountSettings/accountSettingsCommon.ts new file mode 100644 index 000000000..d5a231c09 --- /dev/null +++ b/src/store/accountSettings/accountSettingsCommon.ts @@ -0,0 +1,6 @@ +export const stateKey = 'accountSettings'; +export const accountSettingsKey = 'accountSettings'; + +export function getReportId() { + return `accountSettings`; +} diff --git a/src/store/accountSettings/accountSettingsReducer.ts b/src/store/accountSettings/accountSettingsReducer.ts new file mode 100644 index 000000000..ed3c00b46 --- /dev/null +++ b/src/store/accountSettings/accountSettingsReducer.ts @@ -0,0 +1,66 @@ +import { AccountSettings } from 'api/accountSettings'; +import { AxiosError } from 'axios'; +import { FetchStatus } from 'store/common'; +import { ActionType, getType } from 'typesafe-actions'; +import { invalidateCostType, isCostTypeAvailable, setCostType } from 'utils/localStorage'; + +import { + fetchAccountSettingsFailure, + fetchAccountSettingsRequest, + fetchAccountSettingsSuccess, +} from './accountSettingsActions'; + +export type AccountSettingsState = Readonly<{ + byId: Map; + errors: Map; + fetchStatus: Map; +}>; + +export const defaultState: AccountSettingsState = { + byId: new Map(), + errors: new Map(), + fetchStatus: new Map(), +}; + +export type AccountSettingsAction = ActionType< + typeof fetchAccountSettingsFailure | typeof fetchAccountSettingsRequest | typeof fetchAccountSettingsSuccess +>; + +export function accountSettingsReducer(state = defaultState, action: AccountSettingsAction): AccountSettingsState { + switch (action.type) { + case getType(fetchAccountSettingsRequest): + return { + ...state, + fetchStatus: new Map(state.fetchStatus).set(action.payload.reportId, FetchStatus.inProgress), + }; + case getType(fetchAccountSettingsSuccess): + initCostType(action.payload.meta['cost-type']); + + return { + ...state, + fetchStatus: new Map(state.fetchStatus).set(action.meta.reportId, FetchStatus.complete), + byId: new Map(state.byId).set(action.meta.reportId, { + ...action.payload, + }), + errors: new Map(state.errors).set(action.meta.reportId, null), + }; + case getType(fetchAccountSettingsFailure): + return { + ...state, + fetchStatus: new Map(state.fetchStatus).set(action.meta.reportId, FetchStatus.complete), + errors: new Map(state.errors).set(action.meta.reportId, action.payload), + }; + default: + return state; + } +} + +// Initialize default cost type in local storage +function initCostType(accountSettings) { + // Clear local storage value if current session is not valid + invalidateCostType(); + + if (!isCostTypeAvailable()) { + setCostType(accountSettings); + } +} diff --git a/src/store/accountSettings/accountSettingsSelectors.ts b/src/store/accountSettings/accountSettingsSelectors.ts new file mode 100644 index 000000000..8643b6b15 --- /dev/null +++ b/src/store/accountSettings/accountSettingsSelectors.ts @@ -0,0 +1,15 @@ +import { RootState } from 'store/rootReducer'; + +import { getReportId, stateKey } from './accountSettingsCommon'; + +export const selectAccountSettingsState = (state: RootState) => state[stateKey]; + +// Fetch account settings + +export const selectAccountSettings = (state: RootState) => selectAccountSettingsState(state).byId.get(getReportId()); + +export const selectAccountSettingsFetchStatus = (state: RootState) => + selectAccountSettingsState(state).fetchStatus.get(getReportId()); + +export const selectAccountSettingsError = (state: RootState) => + selectAccountSettingsState(state).errors.get(getReportId()); diff --git a/src/store/accountSettings/index.ts b/src/store/accountSettings/index.ts new file mode 100644 index 000000000..fd7c6dacc --- /dev/null +++ b/src/store/accountSettings/index.ts @@ -0,0 +1,13 @@ +import * as accountSettingsActions from './accountSettingsActions'; +import { stateKey as accountSettingsStateKey } from './accountSettingsCommon'; +import { AccountSettingsAction, accountSettingsReducer, AccountSettingsState } from './accountSettingsReducer'; +import * as accountSettingsSelectors from './accountSettingsSelectors'; + +export { + AccountSettingsAction, + accountSettingsActions, + accountSettingsReducer, + accountSettingsSelectors, + AccountSettingsState, + accountSettingsStateKey, +}; From 7320f2c4a862994789d215a0a5c1ac745a896e10 Mon Sep 17 00:00:00 2001 From: Dan Labrecque Date: Thu, 13 Jan 2022 16:10:24 -0500 Subject: [PATCH 03/29] Modified pages to call AccountSettings instead of CostType wrapper --- src/api/currency.ts | 4 +- .../views/components/costType/costType.tsx | 67 +++------ .../components/costType/costTypeWrapper.tsx | 138 ------------------ src/pages/views/components/costType/index.ts | 3 +- .../awsBreakdown/awsBreakdownWrapper.tsx | 6 +- .../details/awsDetails/awsDetailsWrapper.tsx | 6 +- src/pages/views/explorer/explorerWrapper.tsx | 6 +- src/pages/views/overview/overviewWrapper.tsx | 6 +- src/store/rootReducer.ts | 2 + 9 files changed, 38 insertions(+), 200 deletions(-) delete mode 100644 src/pages/views/components/costType/costTypeWrapper.tsx diff --git a/src/api/currency.ts b/src/api/currency.ts index 69cb39c13..ae2f37678 100644 --- a/src/api/currency.ts +++ b/src/api/currency.ts @@ -15,9 +15,9 @@ export function fetchCurrency() { const insights = (window as any).insights; if (insights && insights.chrome && insights.chrome.auth && insights.chrome.auth.getUser) { return insights.chrome.auth.getUser().then(() => { - return axios.get(`currency/?limit=20`); + return axios.get(`currency/?limit=100`); }); } else { - return axios.get(`currency/?limit=20`); + return axios.get(`currency/?limit=100`); } } diff --git a/src/pages/views/components/costType/costType.tsx b/src/pages/views/components/costType/costType.tsx index fdfa3605a..438078c07 100644 --- a/src/pages/views/components/costType/costType.tsx +++ b/src/pages/views/components/costType/costType.tsx @@ -1,14 +1,13 @@ import './costType.scss'; +import { MessageDescriptor } from '@formatjs/intl/src/types'; import { Select, SelectOption, SelectOptionObject, SelectVariant, Title } from '@patternfly/react-core'; import { CostType } from 'api/costType'; -import { AxiosError } from 'axios'; import messages from 'locales/messages'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; -import { createMapStateToProps, FetchStatus } from 'store/common'; -import { costTypeSelectors } from 'store/costType'; +import { createMapStateToProps } from 'store/common'; import { CostTypes, getCostType, setCostType } from 'utils/localStorage'; import { styles } from './costType.styles'; @@ -23,9 +22,7 @@ interface CostTypeDispatchProps { } interface CostTypeStateProps { - costType: CostType; - costTypeError: AxiosError; - costTypeFetchStatus?: FetchStatus; + // TBD... } interface CostTypeState { @@ -40,6 +37,16 @@ interface CostTypeOption extends SelectOptionObject { type CostTypeProps = CostTypeOwnProps & CostTypeDispatchProps & CostTypeStateProps & WrappedComponentProps; +const costTypeOptions: { + desc: MessageDescriptor; + label: MessageDescriptor; + value: string; +}[] = [ + { desc: messages.CostTypeAmortizedDesc, label: messages.CostTypeAmortized, value: CostTypes.amortized }, + { desc: messages.CostTypeBlendedDesc, label: messages.CostTypeBlended, value: CostTypes.blended }, + { desc: messages.CostTypeUnblendedDesc, label: messages.CostTypeUnblended, value: CostTypes.unblended }, +]; + class CostTypeBase extends React.Component { protected defaultState: CostTypeState = { isSelectOpen: false, @@ -73,43 +80,17 @@ class CostTypeBase extends React.Component { }; private getSelectOptions = (): CostTypeOption[] => { - const { costType, intl } = this.props; + const { intl } = this.props; const options: CostTypeOption[] = []; - if (costType) { - costType.data.map(val => { - switch (val.code) { - case CostTypes.amortized: - options.push({ - desc: intl.formatMessage(messages.CostTypeAmortizedDesc), - toString: () => intl.formatMessage(messages.CostTypeAmortized), - value: CostTypes.amortized, - }); - break; - case CostTypes.blended: - options.push({ - desc: intl.formatMessage(messages.CostTypeBlendedDesc), - toString: () => intl.formatMessage(messages.CostTypeBlended), - value: CostTypes.blended, - }); - break; - case CostTypes.unblended: - options.push({ - desc: intl.formatMessage(messages.CostTypeUnblendedDesc), - toString: () => intl.formatMessage(messages.CostTypeUnblended), - value: CostTypes.unblended, - }); - break; - } - }); - } else { + costTypeOptions.map(option => { options.push({ - desc: intl.formatMessage(messages.CostTypeUnblendedDesc), - toString: () => intl.formatMessage(messages.CostTypeUnblended), - value: CostTypes.unblended, + desc: intl.formatMessage(option.desc), + toString: () => intl.formatMessage(option.label), + value: option.value, }); - } + }); return options; }; @@ -148,15 +129,9 @@ class CostTypeBase extends React.Component { } } -const mapStateToProps = createMapStateToProps(state => { - const costType = costTypeSelectors.selectCostType(state); - const costTypeError = costTypeSelectors.selectCostTypeError(state); - const costTypeFetchStatus = costTypeSelectors.selectCostTypeFetchStatus(state); - +const mapStateToProps = createMapStateToProps(() => { return { - costType, - costTypeError, - costTypeFetchStatus, + // TBD... }; }); diff --git a/src/pages/views/components/costType/costTypeWrapper.tsx b/src/pages/views/components/costType/costTypeWrapper.tsx deleted file mode 100644 index 04ba021a3..000000000 --- a/src/pages/views/components/costType/costTypeWrapper.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { CostType } from 'api/costType'; -import { Providers, ProviderType } from 'api/providers'; -import { getProvidersQuery } from 'api/queries/providersQuery'; -import { getUserAccessQuery } from 'api/queries/userAccessQuery'; -import { UserAccess, UserAccessType } from 'api/userAccess'; -import { AxiosError } from 'axios'; -import React from 'react'; -import { injectIntl, WrappedComponentProps } from 'react-intl'; -import { connect } from 'react-redux'; -import { createMapStateToProps, FetchStatus } from 'store/common'; -import { costTypeActions, costTypeSelectors } from 'store/costType'; -import { awsProvidersQuery, providersSelectors } from 'store/providers'; -import { allUserAccessQuery, userAccessSelectors } from 'store/userAccess'; -import { CostTypes } from 'utils/localStorage'; -import { isAwsAvailable } from 'utils/userAccess'; - -interface CostTypeWrapperOwnProps { - children?: React.ReactNode; -} - -interface CostTypeWrapperDispatchProps { - fetchCostType?: typeof costTypeActions.fetchCostType; -} - -interface CostTypeWrapperStateProps { - awsProviders: Providers; - awsProvidersFetchStatus: FetchStatus; - awsProvidersQueryString: string; - costType: CostType; - costTypeError: AxiosError; - costTypeFetchStatus?: FetchStatus; - userAccess: UserAccess; - userAccessError: AxiosError; - userAccessFetchStatus: FetchStatus; - userAccessQueryString: string; -} - -interface CostTypeWrapperState { - currentCostType?: CostTypes; -} - -type CostTypeWrapperProps = CostTypeWrapperOwnProps & - CostTypeWrapperDispatchProps & - CostTypeWrapperStateProps & - WrappedComponentProps; - -class CostTypeWrapperBase extends React.Component { - protected defaultState: CostTypeWrapperState = { - // TBD... - }; - public state: CostTypeWrapperState = { ...this.defaultState }; - - public componentDidMount() { - this.updateCostType(); - } - - public componentDidUpdate(prevProps: CostTypeWrapperProps) { - const { awsProviders, costType } = this.props; - - if (prevProps.awsProviders !== awsProviders) { - this.updateCostType(); - } else if (prevProps.costType !== costType) { - const currentCostType = costType ? costType.meta['cost-type'] : CostTypes.unblended; - - this.setState({ - currentCostType, - }); - } - } - - private isAwsAvailable = () => { - const { awsProviders, userAccess } = this.props; - return isAwsAvailable(userAccess, awsProviders); - }; - - private updateCostType = () => { - const { costTypeFetchStatus, fetchCostType } = this.props; - - if (this.isAwsAvailable() && costTypeFetchStatus !== FetchStatus.inProgress) { - fetchCostType(); - } - }; - - public render() { - const { awsProvidersFetchStatus, children } = this.props; - const { currentCostType } = this.state; - - if (!this.isAwsAvailable() && awsProvidersFetchStatus === FetchStatus.complete) { - return children; - } - return currentCostType ? children : null; - } -} - -const mapStateToProps = createMapStateToProps(state => { - const awsProvidersQueryString = getProvidersQuery(awsProvidersQuery); - const awsProviders = providersSelectors.selectProviders(state, ProviderType.aws, awsProvidersQueryString); - const awsProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.aws, - awsProvidersQueryString - ); - - const costType = costTypeSelectors.selectCostType(state); - const costTypeError = costTypeSelectors.selectCostTypeError(state); - const costTypeFetchStatus = costTypeSelectors.selectCostTypeFetchStatus(state); - - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); - const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); - const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); - const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( - state, - UserAccessType.all, - userAccessQueryString - ); - - return { - awsProviders, - awsProvidersFetchStatus, - awsProvidersQueryString, - costType, - costTypeError, - costTypeFetchStatus, - userAccess, - userAccessError, - userAccessFetchStatus, - userAccessQueryString, - }; -}); - -const mapDispatchToProps: CostTypeWrapperDispatchProps = { - fetchCostType: costTypeActions.fetchCostType, -}; - -const CostTypeConnect = connect(mapStateToProps, mapDispatchToProps)(CostTypeWrapperBase); -const CostTypeWrapper = injectIntl(CostTypeConnect); - -export { CostTypeWrapper }; diff --git a/src/pages/views/components/costType/index.ts b/src/pages/views/components/costType/index.ts index ce321ed5a..1cd8d4213 100644 --- a/src/pages/views/components/costType/index.ts +++ b/src/pages/views/components/costType/index.ts @@ -1,4 +1,3 @@ import { CostType } from './costType'; -import { CostTypeWrapper } from './costTypeWrapper'; -export { CostType, CostTypeWrapper }; +export { CostType }; diff --git a/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx b/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx index 345c127ab..b350217d0 100644 --- a/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx +++ b/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx @@ -1,4 +1,4 @@ -import { CostTypeWrapper } from 'pages/views/components/costType'; +import { AccountSettings } from 'pages/views/components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; @@ -8,9 +8,9 @@ type AwsBreakdownWrapperProps = RouteComponentProps; const AwsBreakdownWrapper: React.FunctionComponent = props => { return ( - + - + ); }; diff --git a/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx b/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx index bca2183dd..3fe3f0ff3 100644 --- a/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx +++ b/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx @@ -1,4 +1,4 @@ -import { CostTypeWrapper } from 'pages/views/components/costType'; +import { AccountSettings } from 'pages/views/components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; @@ -8,9 +8,9 @@ type AwsDetailsWrapperProps = RouteComponentProps; const AwsDetailsWrapper: React.FunctionComponent = props => { return ( - + - + ); }; diff --git a/src/pages/views/explorer/explorerWrapper.tsx b/src/pages/views/explorer/explorerWrapper.tsx index 6b2b0b3ee..0d1e3d88a 100644 --- a/src/pages/views/explorer/explorerWrapper.tsx +++ b/src/pages/views/explorer/explorerWrapper.tsx @@ -1,4 +1,4 @@ -import { CostTypeWrapper } from 'pages/views/components/costType'; +import { AccountSettings } from 'pages/views/components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; @@ -8,9 +8,9 @@ type ExplorerWrapperProps = RouteComponentProps; const ExplorerWrapper: React.FunctionComponent = props => { return ( - + - + ); }; diff --git a/src/pages/views/overview/overviewWrapper.tsx b/src/pages/views/overview/overviewWrapper.tsx index d5dbd141f..d4af632db 100644 --- a/src/pages/views/overview/overviewWrapper.tsx +++ b/src/pages/views/overview/overviewWrapper.tsx @@ -1,4 +1,4 @@ -import { CostTypeWrapper } from 'pages/views/components/costType'; +import { AccountSettings } from 'pages/views/components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; @@ -8,9 +8,9 @@ type OverviewWrapperProps = RouteComponentProps; const OverviewWrapper: React.FunctionComponent = props => { return ( - + - + ); }; diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts index d2ec24fe9..b670fd5a6 100644 --- a/src/store/rootReducer.ts +++ b/src/store/rootReducer.ts @@ -1,5 +1,6 @@ import { notifications } from '@redhat-cloud-services/frontend-components-notifications'; import { combineReducers } from 'redux'; +import { accountSettingsReducer, accountSettingsStateKey } from 'store/accountSettings'; import { awsCostOverviewReducer, awsCostOverviewStateKey } from 'store/breakdown/costOverview/awsCostOverview'; import { azureCostOverviewReducer, azureCostOverviewStateKey } from 'store/breakdown/costOverview/azureCostOverview'; import { gcpCostOverviewReducer, gcpCostOverviewStateKey } from 'store/breakdown/costOverview/gcpCostOverview'; @@ -43,6 +44,7 @@ import { userAccessReducer, userAccessStateKey } from './userAccess'; export type RootState = StateType; export const rootReducer = combineReducers({ + [accountSettingsStateKey]: accountSettingsReducer, [awsOcpDashboardStateKey]: awsOcpDashboardReducer, [awsCostOverviewStateKey]: awsCostOverviewReducer, [awsDashboardStateKey]: awsDashboardReducer, From 6fc2e5398560788f195587e7ca0f6fab7e869443 Mon Sep 17 00:00:00 2001 From: Dan Labrecque Date: Fri, 14 Jan 2022 09:24:31 -0500 Subject: [PATCH 04/29] Removed cost-type API support --- .../__snapshots__/costType.test.ts.snap | 9 --- src/store/costType/costType.test.ts | 58 ----------------- src/store/costType/costTypeActions.ts | 31 ---------- src/store/costType/costTypeCommon.ts | 6 -- src/store/costType/costTypeReducer.ts | 62 ------------------- src/store/costType/costTypeSelectors.ts | 14 ----- src/store/costType/index.ts | 6 -- src/store/rootReducer.ts | 2 - 8 files changed, 188 deletions(-) delete mode 100644 src/store/costType/__snapshots__/costType.test.ts.snap delete mode 100644 src/store/costType/costType.test.ts delete mode 100644 src/store/costType/costTypeActions.ts delete mode 100644 src/store/costType/costTypeCommon.ts delete mode 100644 src/store/costType/costTypeReducer.ts delete mode 100644 src/store/costType/costTypeSelectors.ts delete mode 100644 src/store/costType/index.ts diff --git a/src/store/costType/__snapshots__/costType.test.ts.snap b/src/store/costType/__snapshots__/costType.test.ts.snap deleted file mode 100644 index 66ab1bd23..000000000 --- a/src/store/costType/__snapshots__/costType.test.ts.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`default state 1`] = ` -Object { - "byId": Map {}, - "errors": Map {}, - "fetchStatus": Map {}, -} -`; diff --git a/src/store/costType/costType.test.ts b/src/store/costType/costType.test.ts deleted file mode 100644 index d83814d86..000000000 --- a/src/store/costType/costType.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -jest.mock('api/costType'); - -import { waitFor } from '@testing-library/react'; -import { CostType, fetchCostType } from 'api/costType'; -import { FetchStatus } from 'store/common'; -import { createMockStoreCreator } from 'store/mockStore'; - -import * as actions from './costTypeActions'; -import { stateKey } from './costTypeCommon'; -import { costTypeReducer } from './costTypeReducer'; -import * as selectors from './costTypeSelectors'; - -const createProdvidersStore = createMockStoreCreator({ - [stateKey]: costTypeReducer, -}); - -const fetchCostTypeMock = fetchCostType as jest.Mock; - -const costTypeMock: CostType = { - data: [ - { - code: 'unblended_cost', - description: 'Unblended', - name: 'Usage cost on the day you are charged', - }, - ], -}; - -fetchCostTypeMock.mockReturnValue(Promise.resolve({ data: costTypeMock })); - -jest.spyOn(selectors, 'selectCostTypeFetchStatus'); - -test('default state', async () => { - const store = createProdvidersStore(); - expect(selectors.selectCostTypeState(store.getState())).toMatchSnapshot(); -}); - -test('fetch costType success', async () => { - const store = createProdvidersStore(); - store.dispatch(actions.fetchCostType()); - expect(fetchCostTypeMock).toBeCalled(); - expect(selectors.selectCostTypeFetchStatus(store.getState())).toBe(FetchStatus.inProgress); - await waitFor(() => expect(selectors.selectCostTypeFetchStatus).toHaveBeenCalled()); - const finishedState = store.getState(); - expect(selectors.selectCostTypeFetchStatus(finishedState)).toBe(FetchStatus.complete); -}); - -test('fetch costType failure', async () => { - const store = createProdvidersStore(); - const error = Symbol('getCostType error'); - fetchCostTypeMock.mockReturnValueOnce(Promise.reject(error)); - store.dispatch(actions.fetchCostType()); - expect(fetchCostTypeMock).toBeCalled(); - expect(selectors.selectCostTypeFetchStatus(store.getState())).toBe(FetchStatus.inProgress); - await waitFor(() => expect(selectors.selectCostTypeFetchStatus).toHaveBeenCalled()); - const finishedState = store.getState(); - expect(selectors.selectCostTypeFetchStatus(finishedState)).toBe(FetchStatus.complete); -}); diff --git a/src/store/costType/costTypeActions.ts b/src/store/costType/costTypeActions.ts deleted file mode 100644 index 0255146a7..000000000 --- a/src/store/costType/costTypeActions.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { CostType, fetchCostType as apiGetCostType } from 'api/costType'; -import { AxiosError } from 'axios'; -import { createAction } from 'typesafe-actions'; - -import { getReportId } from './costTypeCommon'; - -interface CostTypeActionMeta { - reportId: string; -} - -export const fetchCostTypeRequest = createAction('costType/fetch/request')(); -export const fetchCostTypeSuccess = createAction('costType/fetch/success')(); -export const fetchCostTypeFailure = createAction('costType/fetch/failure')(); - -export function fetchCostType() { - return dispatch => { - const meta: CostTypeActionMeta = { - reportId: getReportId(), - }; - - dispatch(fetchCostTypeRequest(meta)); - - return apiGetCostType() - .then(res => { - dispatch(fetchCostTypeSuccess(res.data, meta)); - }) - .catch(err => { - dispatch(fetchCostTypeFailure(err, meta)); - }); - }; -} diff --git a/src/store/costType/costTypeCommon.ts b/src/store/costType/costTypeCommon.ts deleted file mode 100644 index 5ff63f701..000000000 --- a/src/store/costType/costTypeCommon.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const stateKey = 'costType'; -export const costTypeKey = 'costType'; - -export function getReportId() { - return `costType`; -} diff --git a/src/store/costType/costTypeReducer.ts b/src/store/costType/costTypeReducer.ts deleted file mode 100644 index c06bf0426..000000000 --- a/src/store/costType/costTypeReducer.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { CostType } from 'api/costType'; -import { AxiosError } from 'axios'; -import { FetchStatus } from 'store/common'; -import { ActionType, getType } from 'typesafe-actions'; -import { invalidateCostType, isCostTypeAvailable, setCostType } from 'utils/localStorage'; - -import { fetchCostTypeFailure, fetchCostTypeRequest, fetchCostTypeSuccess } from './costTypeActions'; - -export type CostTypeState = Readonly<{ - byId: Map; - errors: Map; - fetchStatus: Map; -}>; - -export const defaultState: CostTypeState = { - byId: new Map(), - errors: new Map(), - fetchStatus: new Map(), -}; - -export type CostTypeAction = ActionType< - typeof fetchCostTypeFailure | typeof fetchCostTypeRequest | typeof fetchCostTypeSuccess ->; - -export function costTypeReducer(state = defaultState, action: CostTypeAction): CostTypeState { - switch (action.type) { - case getType(fetchCostTypeRequest): - return { - ...state, - fetchStatus: new Map(state.fetchStatus).set(action.payload.reportId, FetchStatus.inProgress), - }; - case getType(fetchCostTypeSuccess): - initCostType(action.payload.meta['cost-type']); - - return { - ...state, - fetchStatus: new Map(state.fetchStatus).set(action.meta.reportId, FetchStatus.complete), - byId: new Map(state.byId).set(action.meta.reportId, { - ...action.payload, - }), - errors: new Map(state.errors).set(action.meta.reportId, null), - }; - case getType(fetchCostTypeFailure): - return { - ...state, - fetchStatus: new Map(state.fetchStatus).set(action.meta.reportId, FetchStatus.complete), - errors: new Map(state.errors).set(action.meta.reportId, action.payload), - }; - default: - return state; - } -} - -// Initialize default cost type in local storage -function initCostType(costType) { - // Clear local storage value if current session is not valid - invalidateCostType(); - - if (!isCostTypeAvailable()) { - setCostType(costType); - } -} diff --git a/src/store/costType/costTypeSelectors.ts b/src/store/costType/costTypeSelectors.ts deleted file mode 100644 index 11d5b6e9f..000000000 --- a/src/store/costType/costTypeSelectors.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { RootState } from 'store/rootReducer'; - -import { getReportId, stateKey } from './costTypeCommon'; - -export const selectCostTypeState = (state: RootState) => state[stateKey]; - -// Fetch costType - -export const selectCostType = (state: RootState) => selectCostTypeState(state).byId.get(getReportId()); - -export const selectCostTypeFetchStatus = (state: RootState) => - selectCostTypeState(state).fetchStatus.get(getReportId()); - -export const selectCostTypeError = (state: RootState) => selectCostTypeState(state).errors.get(getReportId()); diff --git a/src/store/costType/index.ts b/src/store/costType/index.ts deleted file mode 100644 index 5bc8b08f5..000000000 --- a/src/store/costType/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as costTypeActions from './costTypeActions'; -import { stateKey as costTypeStateKey } from './costTypeCommon'; -import { CostTypeAction, costTypeReducer, CostTypeState } from './costTypeReducer'; -import * as costTypeSelectors from './costTypeSelectors'; - -export { CostTypeAction, costTypeActions, costTypeReducer, costTypeSelectors, CostTypeState, costTypeStateKey }; diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts index b670fd5a6..27a8b9e73 100644 --- a/src/store/rootReducer.ts +++ b/src/store/rootReducer.ts @@ -34,7 +34,6 @@ import { sourcesReducer, sourcesStateKey } from 'store/sourceSettings'; import { tagReducer, tagStateKey } from 'store/tags'; import { StateType } from 'typesafe-actions'; -import { costTypeReducer, costTypeStateKey } from './costType'; import { currencyReducer, currencyStateKey } from './currency'; import { metricsReducer, metricsStateKey } from './metrics'; import { providersReducer, providersStateKey } from './providers'; @@ -54,7 +53,6 @@ export const rootReducer = combineReducers({ [azureDashboardStateKey]: azureDashboardReducer, [azureHistoricalDataStateKey]: azureHistoricalDataReducer, [costModelsStateKey]: costModelsReducer, - [costTypeStateKey]: costTypeReducer, [currencyStateKey]: currencyReducer, [exportStateKey]: exportReducer, [gcpCostOverviewStateKey]: gcpCostOverviewReducer, From 521e6632d02cfa70c50f8b407efd09343d9d8553 Mon Sep 17 00:00:00 2001 From: Dan Labrecque Date: Fri, 14 Jan 2022 09:24:50 -0500 Subject: [PATCH 05/29] Removed unused ci environment --- scripts/start-dev-server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/start-dev-server.js b/scripts/start-dev-server.js index 522cb5fc8..69b6ae5b1 100644 --- a/scripts/start-dev-server.js +++ b/scripts/start-dev-server.js @@ -16,7 +16,7 @@ async function setEnv() { type: 'list', name: 'clouddotEnv', message: 'Which platform environment you want to use?', - choices: ['stage', 'prod', 'ci'], + choices: ['stage', 'prod'], }, { type: 'list', From a983bf8a6591ff8936b7fe3e31759e3357416770 Mon Sep 17 00:00:00 2001 From: Dan Labrecque Date: Fri, 14 Jan 2022 09:40:19 -0500 Subject: [PATCH 06/29] Rename AccountSettingsWrapper as AccountSettings --- .../accountSettings/accountSettings.tsx | 76 +++++++++---------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/src/pages/views/components/accountSettings/accountSettings.tsx b/src/pages/views/components/accountSettings/accountSettings.tsx index 3e96e4e9f..c270ccb9c 100644 --- a/src/pages/views/components/accountSettings/accountSettings.tsx +++ b/src/pages/views/components/accountSettings/accountSettings.tsx @@ -10,15 +10,15 @@ import { createMapStateToProps, FetchStatus } from 'store/common'; import { allUserAccessQuery, userAccessSelectors } from 'store/userAccess'; import { CostTypes } from 'utils/localStorage'; -interface AccountSettingsWrapperOwnProps { +interface AccountSettingsOwnProps { children?: React.ReactNode; } -interface AccountSettingsWrapperDispatchProps { +interface AccountSettingsDispatchProps { fetchAccountSettings?: typeof accountSettingsActions.fetchAccountSettings; } -interface AccountSettingsWrapperStateProps { +interface AccountSettingsStateProps { accountSettings: AccountSettings; accountSettingsError: AxiosError; accountSettingsFetchStatus?: FetchStatus; @@ -28,27 +28,27 @@ interface AccountSettingsWrapperStateProps { userAccessQueryString: string; } -interface AccountSettingsWrapperState { +interface AccountSettingsState { costType?: CostTypes; currency?: string; } -type AccountSettingsWrapperProps = AccountSettingsWrapperOwnProps & - AccountSettingsWrapperDispatchProps & - AccountSettingsWrapperStateProps & +type AccountSettingsProps = AccountSettingsOwnProps & + AccountSettingsDispatchProps & + AccountSettingsStateProps & WrappedComponentProps; -class AccountSettingsWrapperBase extends React.Component { - protected defaultState: AccountSettingsWrapperState = { +class AccountSettingsBase extends React.Component { + protected defaultState: AccountSettingsState = { // TBD... }; - public state: AccountSettingsWrapperState = { ...this.defaultState }; + public state: AccountSettingsState = { ...this.defaultState }; public componentDidMount() { this.updateAccountSettings(); } - public componentDidUpdate(prevProps: AccountSettingsWrapperProps) { + public componentDidUpdate(prevProps: AccountSettingsProps) { const { accountSettings } = this.props; if (prevProps.accountSettings !== accountSettings) { @@ -82,38 +82,36 @@ class AccountSettingsWrapperBase extends React.Component( - state => { - const accountSettings = accountSettingsSelectors.selectAccountSettings(state); - const accountSettingsError = accountSettingsSelectors.selectAccountSettingsError(state); - const accountSettingsFetchStatus = accountSettingsSelectors.selectAccountSettingsFetchStatus(state); - - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); - const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); - const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); - const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( - state, - UserAccessType.all, - userAccessQueryString - ); - - return { - accountSettings, - accountSettingsError, - accountSettingsFetchStatus, - userAccess, - userAccessError, - userAccessFetchStatus, - userAccessQueryString, - }; - } -); +const mapStateToProps = createMapStateToProps(state => { + const accountSettings = accountSettingsSelectors.selectAccountSettings(state); + const accountSettingsError = accountSettingsSelectors.selectAccountSettingsError(state); + const accountSettingsFetchStatus = accountSettingsSelectors.selectAccountSettingsFetchStatus(state); + + const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); + const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); + const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( + state, + UserAccessType.all, + userAccessQueryString + ); + + return { + accountSettings, + accountSettingsError, + accountSettingsFetchStatus, + userAccess, + userAccessError, + userAccessFetchStatus, + userAccessQueryString, + }; +}); -const mapDispatchToProps: AccountSettingsWrapperDispatchProps = { +const mapDispatchToProps: AccountSettingsDispatchProps = { fetchAccountSettings: accountSettingsActions.fetchAccountSettings, }; -const CostTypeConnect = connect(mapStateToProps, mapDispatchToProps)(AccountSettingsWrapperBase); +const CostTypeConnect = connect(mapStateToProps, mapDispatchToProps)(AccountSettingsBase); const AccountSettings = injectIntl(CostTypeConnect); export { AccountSettings }; From 79d1ff7816f85efe9bd2f50769fac2a37c2f7466 Mon Sep 17 00:00:00 2001 From: Dan Labrecque Date: Fri, 14 Jan 2022 10:01:16 -0500 Subject: [PATCH 07/29] Added currency options to UI and removed currency API request https://issues.redhat.com/browse/COST-2201 --- src/components/currency/currency.tsx | 70 ++++++++++++------- .../accountSettings/accountSettings.tsx | 5 +- .../views/components/costType/costType.tsx | 9 ++- 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/components/currency/currency.tsx b/src/components/currency/currency.tsx index 609f10233..6751522ee 100644 --- a/src/components/currency/currency.tsx +++ b/src/components/currency/currency.tsx @@ -1,5 +1,6 @@ import './currency.scss'; +import { MessageDescriptor } from '@formatjs/intl/src/types'; import { Select, SelectOption, SelectOptionObject, SelectVariant, Title } from '@patternfly/react-core'; import { Currency } from 'api/currency'; import { AxiosError } from 'axios'; @@ -15,6 +16,7 @@ import { styles } from './currency.styles'; interface CurrencyOwnProps { isDisabled?: boolean; + onSelect?: (value: string) => void; } interface CurrencyDispatchProps { @@ -28,7 +30,6 @@ interface CurrencyStateProps { } interface CurrencyState { - currentItem: string; isSelectOpen: boolean; } @@ -39,9 +40,29 @@ interface CurrencyOption extends SelectOptionObject { type CurrencyProps = CurrencyOwnProps & CurrencyDispatchProps & CurrencyStateProps & WrappedComponentProps; +const currencyOptions: { + label: MessageDescriptor; + value: string; +}[] = [ + { label: messages.CurrencyOptions, value: 'AUD' }, + { label: messages.CurrencyOptions, value: 'CAD' }, + { label: messages.CurrencyOptions, value: 'CHF' }, + { label: messages.CurrencyOptions, value: 'CNY' }, + { label: messages.CurrencyOptions, value: 'DKK' }, + { label: messages.CurrencyOptions, value: 'EUR' }, + { label: messages.CurrencyOptions, value: 'GBP' }, + { label: messages.CurrencyOptions, value: 'HKD' }, + { label: messages.CurrencyOptions, value: 'JPY' }, + { label: messages.CurrencyOptions, value: 'NOK' }, + { label: messages.CurrencyOptions, value: 'NZD' }, + { label: messages.CurrencyOptions, value: 'SEK' }, + { label: messages.CurrencyOptions, value: 'SGD' }, + { label: messages.CurrencyOptions, value: 'USD' }, + { label: messages.CurrencyOptions, value: 'ZAR' }, +]; + class CurrencyBase extends React.Component { protected defaultState: CurrencyState = { - currentItem: 'USD', isSelectOpen: false, }; public state: CurrencyState = { ...this.defaultState }; @@ -52,20 +73,13 @@ class CurrencyBase extends React.Component { fetchCurrency(); } - private getCurrentItem = () => { - const { currentItem } = this.state; - - const currencyUnits = getCurrency(); // Get currency units from local storage - return currencyUnits ? currencyUnits : currentItem; - }; - private getSelect = () => { const { isDisabled } = this.props; const { isSelectOpen } = this.state; - const currentItem = this.getCurrentItem(); + const currency = getCurrency(); // Get currency from local storage const selectOptions = this.getSelectOptions(); - const selection = selectOptions.find((option: CurrencyOption) => option.value === currentItem); + const selection = selectOptions.find((option: CurrencyOption) => option.value === currency); return ( { public render() { const { intl } = this.props; + // Clear local storage value if current session is not valid + invalidateCostType(); + return (
From 7dcb7a3a37a320ddb856ace3642899cabbbbaaae Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:43:01 -0500 Subject: [PATCH 08/29] Remove currency and cost-type API support --- src/api/costType.ts | 27 --------- src/api/currency.ts | 23 -------- .../accountSettings/accountSettings.tsx | 4 +- .../components/accountSettings/index.ts | 0 src/components/currency/index.ts | 1 + .../__snapshots__/currency.test.ts.snap | 9 --- src/store/currency/currency.test.ts | 59 ------------------- src/store/currency/currencyActions.ts | 31 ---------- src/store/currency/currencyCommon.ts | 6 -- src/store/currency/currencyReducer.ts | 49 --------------- src/store/currency/currencySelectors.ts | 14 ----- src/store/currency/index.ts | 6 -- 12 files changed, 3 insertions(+), 226 deletions(-) delete mode 100644 src/api/costType.ts delete mode 100644 src/api/currency.ts rename src/{pages/views => }/components/accountSettings/accountSettings.tsx (95%) rename src/{pages/views => }/components/accountSettings/index.ts (100%) create mode 100644 src/components/currency/index.ts delete mode 100644 src/store/currency/__snapshots__/currency.test.ts.snap delete mode 100644 src/store/currency/currency.test.ts delete mode 100644 src/store/currency/currencyActions.ts delete mode 100644 src/store/currency/currencyCommon.ts delete mode 100644 src/store/currency/currencyReducer.ts delete mode 100644 src/store/currency/currencySelectors.ts delete mode 100644 src/store/currency/index.ts diff --git a/src/api/costType.ts b/src/api/costType.ts deleted file mode 100644 index eee7d6c81..000000000 --- a/src/api/costType.ts +++ /dev/null @@ -1,27 +0,0 @@ -import axios from 'axios'; - -import { PagedResponse } from './api'; - -export interface CostTypeData { - code?: string; - description?: string; - name?: string; -} - -export interface CostTypeMeta { - count?: string; - ['cost-type']?: string; -} - -export interface CostType extends PagedResponse<CostTypeData, CostTypeMeta> {} - -export function fetchCostType() { - const insights = (window as any).insights; - if (insights && insights.chrome && insights.chrome.auth && insights.chrome.auth.getUser) { - return insights.chrome.auth.getUser().then(() => { - return axios.get<CostType>(`cost-type/`); - }); - } else { - return axios.get<CostType>(`cost-type/`); - } -} diff --git a/src/api/currency.ts b/src/api/currency.ts deleted file mode 100644 index ae2f37678..000000000 --- a/src/api/currency.ts +++ /dev/null @@ -1,23 +0,0 @@ -import axios from 'axios'; - -import { PagedResponse } from './api'; - -export interface CurrencyData { - code?: string; - description?: string; - name?: string; - symbol?: string; -} - -export interface Currency extends PagedResponse<CurrencyData, CurrencyData> {} - -export function fetchCurrency() { - const insights = (window as any).insights; - if (insights && insights.chrome && insights.chrome.auth && insights.chrome.auth.getUser) { - return insights.chrome.auth.getUser().then(() => { - return axios.get<Currency>(`currency/?limit=100`); - }); - } else { - return axios.get<Currency>(`currency/?limit=100`); - } -} diff --git a/src/pages/views/components/accountSettings/accountSettings.tsx b/src/components/accountSettings/accountSettings.tsx similarity index 95% rename from src/pages/views/components/accountSettings/accountSettings.tsx rename to src/components/accountSettings/accountSettings.tsx index e1bef48a1..aac3c56de 100644 --- a/src/pages/views/components/accountSettings/accountSettings.tsx +++ b/src/components/accountSettings/accountSettings.tsx @@ -53,8 +53,8 @@ class AccountSettingsBase extends React.Component<AccountSettingsProps> { if (prevProps.accountSettings !== accountSettings) { // To do: Adjust meta properties when account-settings API is available - const costType = accountSettings ? accountSettings.meta['cost-type'] : CostTypes.unblended; - const currency = accountSettings ? accountSettings.meta.currency : 'USD'; + const costType = accountSettings ? accountSettings.data.cost_type : CostTypes.unblended; + const currency = accountSettings ? accountSettings.data.currency : 'USD'; // Force update to render children this.setState({ diff --git a/src/pages/views/components/accountSettings/index.ts b/src/components/accountSettings/index.ts similarity index 100% rename from src/pages/views/components/accountSettings/index.ts rename to src/components/accountSettings/index.ts diff --git a/src/components/currency/index.ts b/src/components/currency/index.ts new file mode 100644 index 000000000..b9056001e --- /dev/null +++ b/src/components/currency/index.ts @@ -0,0 +1 @@ +export * from './accountSettings'; diff --git a/src/store/currency/__snapshots__/currency.test.ts.snap b/src/store/currency/__snapshots__/currency.test.ts.snap deleted file mode 100644 index 66ab1bd23..000000000 --- a/src/store/currency/__snapshots__/currency.test.ts.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`default state 1`] = ` -Object { - "byId": Map {}, - "errors": Map {}, - "fetchStatus": Map {}, -} -`; diff --git a/src/store/currency/currency.test.ts b/src/store/currency/currency.test.ts deleted file mode 100644 index c920b644e..000000000 --- a/src/store/currency/currency.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -jest.mock('api/currency'); - -import { waitFor } from '@testing-library/react'; -import { Currency, fetchCurrency } from 'api/currency'; -import { FetchStatus } from 'store/common'; -import { createMockStoreCreator } from 'store/mockStore'; - -import * as actions from './currencyActions'; -import { stateKey } from './currencyCommon'; -import { currencyReducer } from './currencyReducer'; -import * as selectors from './currencySelectors'; - -const createProdvidersStore = createMockStoreCreator({ - [stateKey]: currencyReducer, -}); - -const fetchCurrencyMock = fetchCurrency as jest.Mock; - -const currencyMock: Currency = { - data: [ - { - code: 'USD', - description: 'USD ($) - United States Dollar', - name: 'United States Dollar', - symbol: '$', - }, - ], -}; - -fetchCurrencyMock.mockReturnValue(Promise.resolve({ data: currencyMock })); - -jest.spyOn(selectors, 'selectCurrencyFetchStatus'); - -test('default state', async () => { - const store = createProdvidersStore(); - expect(selectors.selectCurrencyState(store.getState())).toMatchSnapshot(); -}); - -test('fetch currency success', async () => { - const store = createProdvidersStore(); - store.dispatch(actions.fetchCurrency()); - expect(fetchCurrencyMock).toBeCalled(); - expect(selectors.selectCurrencyFetchStatus(store.getState())).toBe(FetchStatus.inProgress); - await waitFor(() => expect(selectors.selectCurrencyFetchStatus).toHaveBeenCalled()); - const finishedState = store.getState(); - expect(selectors.selectCurrencyFetchStatus(finishedState)).toBe(FetchStatus.complete); -}); - -test('fetch currency failure', async () => { - const store = createProdvidersStore(); - const error = Symbol('getCurrency error'); - fetchCurrencyMock.mockReturnValueOnce(Promise.reject(error)); - store.dispatch(actions.fetchCurrency()); - expect(fetchCurrencyMock).toBeCalled(); - expect(selectors.selectCurrencyFetchStatus(store.getState())).toBe(FetchStatus.inProgress); - await waitFor(() => expect(selectors.selectCurrencyFetchStatus).toHaveBeenCalled()); - const finishedState = store.getState(); - expect(selectors.selectCurrencyFetchStatus(finishedState)).toBe(FetchStatus.complete); -}); diff --git a/src/store/currency/currencyActions.ts b/src/store/currency/currencyActions.ts deleted file mode 100644 index c9416e55c..000000000 --- a/src/store/currency/currencyActions.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Currency, fetchCurrency as apiGetCurrency } from 'api/currency'; -import { AxiosError } from 'axios'; -import { createAction } from 'typesafe-actions'; - -import { getReportId } from './currencyCommon'; - -interface CurrencyActionMeta { - reportId: string; -} - -export const fetchCurrencyRequest = createAction('currency/fetch/request')<CurrencyActionMeta>(); -export const fetchCurrencySuccess = createAction('currency/fetch/success')<Currency, CurrencyActionMeta>(); -export const fetchCurrencyFailure = createAction('currency/fetch/failure')<AxiosError, CurrencyActionMeta>(); - -export function fetchCurrency() { - return dispatch => { - const meta: CurrencyActionMeta = { - reportId: getReportId(), - }; - - dispatch(fetchCurrencyRequest(meta)); - - return apiGetCurrency() - .then(res => { - dispatch(fetchCurrencySuccess(res.data, meta)); - }) - .catch(err => { - dispatch(fetchCurrencyFailure(err, meta)); - }); - }; -} diff --git a/src/store/currency/currencyCommon.ts b/src/store/currency/currencyCommon.ts deleted file mode 100644 index 39f43d172..000000000 --- a/src/store/currency/currencyCommon.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const stateKey = 'currency'; -export const currencyKey = 'currency'; - -export function getReportId() { - return `currency`; -} diff --git a/src/store/currency/currencyReducer.ts b/src/store/currency/currencyReducer.ts deleted file mode 100644 index 54f96e879..000000000 --- a/src/store/currency/currencyReducer.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Currency } from 'api/currency'; -import { AxiosError } from 'axios'; -import { FetchStatus } from 'store/common'; -import { ActionType, getType } from 'typesafe-actions'; - -import { fetchCurrencyFailure, fetchCurrencyRequest, fetchCurrencySuccess } from './currencyActions'; - -export type CurrencyState = Readonly<{ - byId: Map<string, Currency>; - errors: Map<string, AxiosError>; - fetchStatus: Map<string, FetchStatus>; -}>; - -export const defaultState: CurrencyState = { - byId: new Map(), - errors: new Map(), - fetchStatus: new Map(), -}; - -export type CurrencyAction = ActionType< - typeof fetchCurrencyFailure | typeof fetchCurrencyRequest | typeof fetchCurrencySuccess ->; - -export function currencyReducer(state = defaultState, action: CurrencyAction): CurrencyState { - switch (action.type) { - case getType(fetchCurrencyRequest): - return { - ...state, - fetchStatus: new Map(state.fetchStatus).set(action.payload.reportId, FetchStatus.inProgress), - }; - case getType(fetchCurrencySuccess): - return { - ...state, - fetchStatus: new Map(state.fetchStatus).set(action.meta.reportId, FetchStatus.complete), - byId: new Map(state.byId).set(action.meta.reportId, { - ...action.payload, - }), - errors: new Map(state.errors).set(action.meta.reportId, null), - }; - case getType(fetchCurrencyFailure): - return { - ...state, - fetchStatus: new Map(state.fetchStatus).set(action.meta.reportId, FetchStatus.complete), - errors: new Map(state.errors).set(action.meta.reportId, action.payload), - }; - default: - return state; - } -} diff --git a/src/store/currency/currencySelectors.ts b/src/store/currency/currencySelectors.ts deleted file mode 100644 index b7ea12f2e..000000000 --- a/src/store/currency/currencySelectors.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { RootState } from 'store/rootReducer'; - -import { getReportId, stateKey } from './currencyCommon'; - -export const selectCurrencyState = (state: RootState) => state[stateKey]; - -// Fetch currency - -export const selectCurrency = (state: RootState) => selectCurrencyState(state).byId.get(getReportId()); - -export const selectCurrencyFetchStatus = (state: RootState) => - selectCurrencyState(state).fetchStatus.get(getReportId()); - -export const selectCurrencyError = (state: RootState) => selectCurrencyState(state).errors.get(getReportId()); diff --git a/src/store/currency/index.ts b/src/store/currency/index.ts deleted file mode 100644 index ff393f79a..000000000 --- a/src/store/currency/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as currencyActions from './currencyActions'; -import { stateKey as currencyStateKey } from './currencyCommon'; -import { CurrencyAction, currencyReducer, CurrencyState } from './currencyReducer'; -import * as currencySelectors from './currencySelectors'; - -export { CurrencyAction, currencyActions, currencyReducer, currencySelectors, CurrencyState, currencyStateKey }; From 2857e0c78bcaf2b19da9dee90a36cacc1b1654eb Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:44:10 -0500 Subject: [PATCH 09/29] Remove currency API support --- src/components/currency/currency.tsx | 31 +++++++--------------------- src/components/currency/index.ts | 2 +- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/components/currency/currency.tsx b/src/components/currency/currency.tsx index 6751522ee..8467181f2 100644 --- a/src/components/currency/currency.tsx +++ b/src/components/currency/currency.tsx @@ -2,14 +2,11 @@ import './currency.scss'; import { MessageDescriptor } from '@formatjs/intl/src/types'; import { Select, SelectOption, SelectOptionObject, SelectVariant, Title } from '@patternfly/react-core'; -import { Currency } from 'api/currency'; -import { AxiosError } from 'axios'; import messages from 'locales/messages'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; -import { createMapStateToProps, FetchStatus } from 'store/common'; -import { currencyActions, currencySelectors } from 'store/currency'; +import { createMapStateToProps } from 'store/common'; import { getCurrency, invalidateCurrency, setCurrency } from 'utils/localStorage'; import { styles } from './currency.styles'; @@ -20,13 +17,11 @@ interface CurrencyOwnProps { } interface CurrencyDispatchProps { - fetchCurrency?: typeof currencyActions.fetchCurrency; + // TBD } interface CurrencyStateProps { - currency: Currency; - currencyError: AxiosError; - currencyFetchStatus?: FetchStatus; + // TBD } interface CurrencyState { @@ -40,7 +35,7 @@ interface CurrencyOption extends SelectOptionObject { type CurrencyProps = CurrencyOwnProps & CurrencyDispatchProps & CurrencyStateProps & WrappedComponentProps; -const currencyOptions: { +export const currencyOptions: { label: MessageDescriptor; value: string; }[] = [ @@ -67,12 +62,6 @@ class CurrencyBase extends React.Component<CurrencyProps> { }; public state: CurrencyState = { ...this.defaultState }; - public componentDidMount() { - const { fetchCurrency } = this.props; - - fetchCurrency(); - } - private getSelect = () => { const { isDisabled } = this.props; const { isSelectOpen } = this.state; @@ -151,20 +140,14 @@ class CurrencyBase extends React.Component<CurrencyProps> { } } -const mapStateToProps = createMapStateToProps<CurrencyOwnProps, CurrencyStateProps>(state => { - const currency = currencySelectors.selectCurrency(state); - const currencyError = currencySelectors.selectCurrencyError(state); - const currencyFetchStatus = currencySelectors.selectCurrencyFetchStatus(state); - +const mapStateToProps = createMapStateToProps<CurrencyOwnProps, CurrencyStateProps>(() => { return { - currency, - currencyError, - currencyFetchStatus, + // TBD }; }); const mapDispatchToProps: CurrencyDispatchProps = { - fetchCurrency: currencyActions.fetchCurrency, + // TBD }; const CurrencyConnect = connect(mapStateToProps, mapDispatchToProps)(CurrencyBase); diff --git a/src/components/currency/index.ts b/src/components/currency/index.ts index b9056001e..ed7723219 100644 --- a/src/components/currency/index.ts +++ b/src/components/currency/index.ts @@ -1 +1 @@ -export * from './accountSettings'; +export * from './currency'; From 64037ef8d33ed545d7ef164aeebe032d629f159d Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:45:13 -0500 Subject: [PATCH 10/29] Remove cost-type API support --- src/pages/views/components/costType/costType.tsx | 1 - src/store/rootReducer.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/pages/views/components/costType/costType.tsx b/src/pages/views/components/costType/costType.tsx index 42c027a82..aca1545e0 100644 --- a/src/pages/views/components/costType/costType.tsx +++ b/src/pages/views/components/costType/costType.tsx @@ -2,7 +2,6 @@ import './costType.scss'; import { MessageDescriptor } from '@formatjs/intl/src/types'; import { Select, SelectOption, SelectOptionObject, SelectVariant, Title } from '@patternfly/react-core'; -import { CostType } from 'api/costType'; import messages from 'locales/messages'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts index 27a8b9e73..a9c648357 100644 --- a/src/store/rootReducer.ts +++ b/src/store/rootReducer.ts @@ -34,7 +34,6 @@ import { sourcesReducer, sourcesStateKey } from 'store/sourceSettings'; import { tagReducer, tagStateKey } from 'store/tags'; import { StateType } from 'typesafe-actions'; -import { currencyReducer, currencyStateKey } from './currency'; import { metricsReducer, metricsStateKey } from './metrics'; import { providersReducer, providersStateKey } from './providers'; import { rbacReducer, rbacStateKey } from './rbac'; @@ -53,7 +52,6 @@ export const rootReducer = combineReducers({ [azureDashboardStateKey]: azureDashboardReducer, [azureHistoricalDataStateKey]: azureHistoricalDataReducer, [costModelsStateKey]: costModelsReducer, - [currencyStateKey]: currencyReducer, [exportStateKey]: exportReducer, [gcpCostOverviewStateKey]: gcpCostOverviewReducer, [gcpDashboardStateKey]: gcpDashboardReducer, From d2f62cdfa4f9b177e7c41077a63be6bafcef5d99 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:46:00 -0500 Subject: [PATCH 11/29] Move AccountSettings to components directory --- src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx | 2 +- src/pages/views/details/awsDetails/awsDetailsWrapper.tsx | 2 +- src/pages/views/details/awsDetails/detailsHeader.tsx | 2 +- src/pages/views/details/azureDetails/detailsHeader.tsx | 2 +- .../views/details/components/breakdown/breakdownHeader.tsx | 2 +- src/pages/views/details/gcpDetails/detailsHeader.tsx | 2 +- src/pages/views/details/ibmDetails/detailsHeader.tsx | 2 +- src/pages/views/details/ocpDetails/detailsHeader.tsx | 2 +- src/pages/views/explorer/explorerHeader.tsx | 2 +- src/pages/views/explorer/explorerWrapper.tsx | 2 +- src/pages/views/overview/overview.tsx | 2 +- src/pages/views/overview/overviewWrapper.tsx | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx b/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx index b350217d0..6b2aad956 100644 --- a/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx +++ b/src/pages/views/details/awsBreakdown/awsBreakdownWrapper.tsx @@ -1,4 +1,4 @@ -import { AccountSettings } from 'pages/views/components/accountSettings'; +import { AccountSettings } from 'components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; diff --git a/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx b/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx index 3fe3f0ff3..5801eb465 100644 --- a/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx +++ b/src/pages/views/details/awsDetails/awsDetailsWrapper.tsx @@ -1,4 +1,4 @@ -import { AccountSettings } from 'pages/views/components/accountSettings'; +import { AccountSettings } from 'components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; diff --git a/src/pages/views/details/awsDetails/detailsHeader.tsx b/src/pages/views/details/awsDetails/detailsHeader.tsx index e4c8c6402..b2d90145c 100644 --- a/src/pages/views/details/awsDetails/detailsHeader.tsx +++ b/src/pages/views/details/awsDetails/detailsHeader.tsx @@ -6,7 +6,7 @@ import { getProvidersQuery } from 'api/queries/providersQuery'; import { AwsReport } from 'api/reports/awsReports'; import { TagPathsType } from 'api/tags/tag'; import { AxiosError } from 'axios'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { CostType } from 'pages/views/components/costType'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; diff --git a/src/pages/views/details/azureDetails/detailsHeader.tsx b/src/pages/views/details/azureDetails/detailsHeader.tsx index d268cd610..a6a8073f3 100644 --- a/src/pages/views/details/azureDetails/detailsHeader.tsx +++ b/src/pages/views/details/azureDetails/detailsHeader.tsx @@ -5,7 +5,7 @@ import { getProvidersQuery } from 'api/queries/providersQuery'; import { AzureReport } from 'api/reports/azureReports'; import { TagPathsType } from 'api/tags/tag'; import { AxiosError } from 'axios'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; import React from 'react'; diff --git a/src/pages/views/details/components/breakdown/breakdownHeader.tsx b/src/pages/views/details/components/breakdown/breakdownHeader.tsx index 00d8d2ac1..0f8a652a2 100644 --- a/src/pages/views/details/components/breakdown/breakdownHeader.tsx +++ b/src/pages/views/details/components/breakdown/breakdownHeader.tsx @@ -5,7 +5,7 @@ import { AngleLeftIcon } from '@patternfly/react-icons/dist/esm/icons/angle-left import { breakdownDescKey, breakdownTitleKey, getQueryRoute, orgUnitIdKey, Query } from 'api/queries/query'; import { Report } from 'api/reports/report'; import { TagPathsType } from 'api/tags/tag'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { CostType } from 'pages/views/components/costType'; import { TagLink } from 'pages/views/details/components/tag/tagLink'; diff --git a/src/pages/views/details/gcpDetails/detailsHeader.tsx b/src/pages/views/details/gcpDetails/detailsHeader.tsx index ab13e3316..2cf198ffa 100644 --- a/src/pages/views/details/gcpDetails/detailsHeader.tsx +++ b/src/pages/views/details/gcpDetails/detailsHeader.tsx @@ -5,7 +5,7 @@ import { getProvidersQuery } from 'api/queries/providersQuery'; import { GcpReport } from 'api/reports/gcpReports'; import { TagPathsType } from 'api/tags/tag'; import { AxiosError } from 'axios'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; import React from 'react'; diff --git a/src/pages/views/details/ibmDetails/detailsHeader.tsx b/src/pages/views/details/ibmDetails/detailsHeader.tsx index b5503de94..bb1ea3920 100644 --- a/src/pages/views/details/ibmDetails/detailsHeader.tsx +++ b/src/pages/views/details/ibmDetails/detailsHeader.tsx @@ -5,7 +5,7 @@ import { getProvidersQuery } from 'api/queries/providersQuery'; import { IbmReport } from 'api/reports/ibmReports'; import { TagPathsType } from 'api/tags/tag'; import { AxiosError } from 'axios'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; import React from 'react'; diff --git a/src/pages/views/details/ocpDetails/detailsHeader.tsx b/src/pages/views/details/ocpDetails/detailsHeader.tsx index 259e346f5..1b7387100 100644 --- a/src/pages/views/details/ocpDetails/detailsHeader.tsx +++ b/src/pages/views/details/ocpDetails/detailsHeader.tsx @@ -5,7 +5,7 @@ import { getProvidersQuery } from 'api/queries/providersQuery'; import { OcpReport } from 'api/reports/ocpReports'; import { TagPathsType } from 'api/tags/tag'; import { AxiosError } from 'axios'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import { EmptyValueState } from 'components/state/emptyValueState/emptyValueState'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; diff --git a/src/pages/views/explorer/explorerHeader.tsx b/src/pages/views/explorer/explorerHeader.tsx index 47e7186db..18f1b57ee 100644 --- a/src/pages/views/explorer/explorerHeader.tsx +++ b/src/pages/views/explorer/explorerHeader.tsx @@ -5,7 +5,7 @@ import { getQuery, parseQuery, Query } from 'api/queries/query'; import { getUserAccessQuery } from 'api/queries/userAccessQuery'; import { UserAccess, UserAccessType } from 'api/userAccess'; import { AxiosError } from 'axios'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { CostType } from 'pages/views/components/costType'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; diff --git a/src/pages/views/explorer/explorerWrapper.tsx b/src/pages/views/explorer/explorerWrapper.tsx index 0d1e3d88a..1a995b2b1 100644 --- a/src/pages/views/explorer/explorerWrapper.tsx +++ b/src/pages/views/explorer/explorerWrapper.tsx @@ -1,4 +1,4 @@ -import { AccountSettings } from 'pages/views/components/accountSettings'; +import { AccountSettings } from 'components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; diff --git a/src/pages/views/overview/overview.tsx b/src/pages/views/overview/overview.tsx index 514f97c42..bbe0e1f10 100644 --- a/src/pages/views/overview/overview.tsx +++ b/src/pages/views/overview/overview.tsx @@ -18,7 +18,7 @@ import { getProvidersQuery } from 'api/queries/providersQuery'; import { getUserAccessQuery } from 'api/queries/userAccessQuery'; import { UserAccess, UserAccessType } from 'api/userAccess'; import { AxiosError } from 'axios'; -import { Currency } from 'components/currency/currency'; +import { Currency } from 'components/currency'; import messages from 'locales/messages'; import Loading from 'pages/state/loading'; import NoData from 'pages/state/noData/noData'; diff --git a/src/pages/views/overview/overviewWrapper.tsx b/src/pages/views/overview/overviewWrapper.tsx index d4af632db..cf254e24c 100644 --- a/src/pages/views/overview/overviewWrapper.tsx +++ b/src/pages/views/overview/overviewWrapper.tsx @@ -1,4 +1,4 @@ -import { AccountSettings } from 'pages/views/components/accountSettings'; +import { AccountSettings } from 'components/accountSettings'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; From 668634508f3f34d257df94d5e6e1f242ffdd65d1 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:46:39 -0500 Subject: [PATCH 12/29] Save original account currency for cost models wizard --- .../accountSettings/accountSettingsReducer.ts | 30 +++++++++++++++---- src/utils/localStorage.ts | 29 ++++++++++++++++-- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/store/accountSettings/accountSettingsReducer.ts b/src/store/accountSettings/accountSettingsReducer.ts index ed3c00b46..70a0d3e4c 100644 --- a/src/store/accountSettings/accountSettingsReducer.ts +++ b/src/store/accountSettings/accountSettingsReducer.ts @@ -2,7 +2,15 @@ import { AccountSettings } from 'api/accountSettings'; import { AxiosError } from 'axios'; import { FetchStatus } from 'store/common'; import { ActionType, getType } from 'typesafe-actions'; -import { invalidateCostType, isCostTypeAvailable, setCostType } from 'utils/localStorage'; +import { + invalidateCostType, + invalidateCurrency, + isCostTypeAvailable, + isCurrencyAvailable, + setAccountCurrency, + setCostType, + setCurrency, +} from 'utils/localStorage'; import { fetchAccountSettingsFailure, @@ -34,7 +42,8 @@ export function accountSettingsReducer(state = defaultState, action: AccountSett fetchStatus: new Map(state.fetchStatus).set(action.payload.reportId, FetchStatus.inProgress), }; case getType(fetchAccountSettingsSuccess): - initCostType(action.payload.meta['cost-type']); + initCostType(action.payload.data.cost_type); + initCurrency(action.payload.data.currency); return { ...state, @@ -55,12 +64,23 @@ export function accountSettingsReducer(state = defaultState, action: AccountSett } } -// Initialize default cost type in local storage -function initCostType(accountSettings) { +// Initialize cost type in local storage +function initCostType(value: string) { // Clear local storage value if current session is not valid invalidateCostType(); if (!isCostTypeAvailable()) { - setCostType(accountSettings); + setCostType(value); + } +} + +// Initialize currency in local storage +function initCurrency(value: string) { + // Clear local storage value if current session is not valid + invalidateCurrency(); + + if (!isCurrencyAvailable()) { + setCurrency(value); } + setAccountCurrency(value); } diff --git a/src/utils/localStorage.ts b/src/utils/localStorage.ts index 504f42473..d702a35ea 100644 --- a/src/utils/localStorage.ts +++ b/src/utils/localStorage.ts @@ -1,7 +1,8 @@ import { parseQuery, Query } from 'api/queries/query'; import { getTokenCookie } from 'utils/cookie'; -const costTypeID = 'cost_type'; +const accountCurrencyID = 'cost_management_account_currency'; +const costTypeID = 'cost_management_cost_type'; const currencyID = 'cost_management_currency'; const inactiveSourcesID = 'cost_management_inactive_sources'; const sessionTokenID = 'cost_management_session'; @@ -31,7 +32,7 @@ export const isSessionValid = () => { return getSessionToken() === getPartialTokenCookie(); }; -// Save inactive sources token +// Save partial session token export const saveSessionToken = () => { localStorage.setItem(sessionTokenID, getPartialTokenCookie()); }; @@ -93,11 +94,22 @@ export const setCostType = (value: string) => { * Currency */ +// Deletes account currency +export const deleteAccountCurrency = () => { + localStorage.removeItem(accountCurrencyID); +}; + // Deletes currency export const deleteCurrency = () => { localStorage.removeItem(currencyID); }; +// Returns account currency +export const getAccountCurrency = () => { + const units = localStorage.getItem(accountCurrencyID); + return units ? units : 'USD'; +}; + // Returns currency export const getCurrency = () => { const units = localStorage.getItem(currencyID); @@ -107,11 +119,24 @@ export const getCurrency = () => { // Invalidates currency if current session is not valid export const invalidateCurrency = () => { if (!isSessionValid()) { + deleteAccountCurrency(); deleteSessionToken(); deleteCurrency(); } }; +// Returns true if currency is available +export const isCurrencyAvailable = () => { + const currency = localStorage.getItem(currencyID); + return currency && currency !== null; +}; + +// Set account currency +export const setAccountCurrency = (value: string) => { + localStorage.setItem(accountCurrencyID, value); + saveSessionToken(); +}; + // Set currency export const setCurrency = (value: string) => { localStorage.setItem(currencyID, value); From f33099fc27ba8f61c74bc648a67c7a5d0cd3eea5 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:47:18 -0500 Subject: [PATCH 13/29] Update cost models wizard to use account settings for currency --- .../createCostModelWizard/context.ts | 3 +- .../generalInformation.tsx | 51 +++++---------- .../createCostModelWizard/index.tsx | 65 ++++++++++--------- 3 files changed, 52 insertions(+), 67 deletions(-) diff --git a/src/pages/costModels/createCostModelWizard/context.ts b/src/pages/costModels/createCostModelWizard/context.ts index cf6ee353d..7ce73b0c9 100644 --- a/src/pages/costModels/createCostModelWizard/context.ts +++ b/src/pages/costModels/createCostModelWizard/context.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { MetricHash } from 'api/metrics'; import React from 'react'; +import { getAccountCurrency } from 'utils/localStorage'; export const defaultCostModelContext = { apiError: null, @@ -9,7 +10,7 @@ export const defaultCostModelContext = { createError: null, createProcess: false, createSuccess: false, - currencyUnits: 'USD', + currencyUnits: getAccountCurrency(), dataFetched: false, description: '', dirtyName: false, diff --git a/src/pages/costModels/createCostModelWizard/generalInformation.tsx b/src/pages/costModels/createCostModelWizard/generalInformation.tsx index 53e78c691..3adec3de1 100644 --- a/src/pages/costModels/createCostModelWizard/generalInformation.tsx +++ b/src/pages/costModels/createCostModelWizard/generalInformation.tsx @@ -9,15 +9,13 @@ import { Title, TitleSizes, } from '@patternfly/react-core'; -import { Currency } from 'api/currency'; -import { AxiosError } from 'axios'; +import { currencyOptions } from 'components/currency'; import { Form } from 'components/forms/form'; import messages from 'locales/messages'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; -import { createMapStateToProps, FetchStatus } from 'store/common'; -import { currencyActions, currencySelectors } from 'store/currency'; +import { createMapStateToProps } from 'store/common'; import { isBetaFeature } from 'utils/feature'; import { CostModelContext } from './context'; @@ -25,19 +23,15 @@ import { descriptionErrors, nameErrors } from './steps'; import { styles } from './wizard.styles'; interface GeneralInformationOwnProps { - currency?: Currency; - currencyError?: AxiosError; - currencyFetchStatus?: FetchStatus; + // TBD } interface GeneralInformationStateProps { - currency: Currency; - currencyError: AxiosError; - currencyFetchStatus?: FetchStatus; + // TBD } interface GeneralInformationDispatchProps { - fetchCurrency?: typeof currencyActions.fetchCurrency; + // TBD } type GeneralInformationProps = GeneralInformationOwnProps & @@ -46,14 +40,8 @@ type GeneralInformationProps = GeneralInformationOwnProps & WrappedComponentProps; class GeneralInformation extends React.Component<GeneralInformationProps> { - public componentDidMount() { - const { fetchCurrency } = this.props; - - fetchCurrency(); - } - public render() { - const { currency, intl } = this.props; + const { intl } = this.props; return ( <CostModelContext.Consumer> @@ -131,14 +119,13 @@ class GeneralInformation extends React.Component<GeneralInformationProps> { isBetaFeature() && ( <FormGroup label={intl.formatMessage(messages.Currency)} fieldId="currency-units"> <FormSelect id="currency-units" value={currencyUnits} onChange={onCurrencyChange}> - {currency && - currency.data.map(val => ( - <FormSelectOption - key={val.code} - label={intl.formatMessage(messages.CurrencyOptions, { units: val.code })} - value={val.code} - /> - ))} + {currencyOptions.map(option => ( + <FormSelectOption + key={option.value} + label={intl.formatMessage(option.label, { units: option.value })} + value={option.value} + /> + ))} </FormSelect> </FormGroup> ) @@ -152,20 +139,14 @@ class GeneralInformation extends React.Component<GeneralInformationProps> { } } -const mapStateToProps = createMapStateToProps<GeneralInformationOwnProps, GeneralInformationStateProps>(state => { - const currency = currencySelectors.selectCurrency(state); - const currencyError = currencySelectors.selectCurrencyError(state); - const currencyFetchStatus = currencySelectors.selectCurrencyFetchStatus(state); - +const mapStateToProps = createMapStateToProps<GeneralInformationOwnProps, GeneralInformationStateProps>(() => { return { - currency, - currencyError, - currencyFetchStatus, + // TBD }; }); const mapDispatchToProps: GeneralInformationDispatchProps = { - fetchCurrency: currencyActions.fetchCurrency, + // TDB }; export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(GeneralInformation)); diff --git a/src/pages/costModels/createCostModelWizard/index.tsx b/src/pages/costModels/createCostModelWizard/index.tsx index 664650a78..649bfdd79 100644 --- a/src/pages/costModels/createCostModelWizard/index.tsx +++ b/src/pages/costModels/createCostModelWizard/index.tsx @@ -4,6 +4,7 @@ import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/esm/icons/ import { addCostModel } from 'api/costModels'; import { MetricHash } from 'api/metrics'; import { Rate } from 'api/rates'; +import { AccountSettings } from 'components/accountSettings'; import messages from 'locales/messages'; import { cloneDeep } from 'lodash'; import React from 'react'; @@ -90,38 +91,40 @@ const InternalWizardBase: React.SFC<InternalWizardBaseProps> = ({ } return isOpen ? ( - <Wizard - isOpen - title={intl.formatMessage(messages.CreateCostModelTitle)} - description={intl.formatMessage(messages.CreateCostModelDesc)} - steps={newSteps} - startAtStep={current} - onNext={onMove} - onBack={onMove} - onGoToStep={onMove} - onClose={closeFnc} - footer={isSuccess || isProcess || isAddingRate ? <div /> : null} - onSave={() => { - const { name, type, tiers, markup, description, distribution, isDiscount, sources } = context; - addCostModel({ - name, - source_type: type, - description, - distribution, - rates: transformTiers(tiers, 'USD', true), // Todo: Temporarily transform to USD for APIs, - markup: { - value: `${isDiscount ? '-' : ''}${unFormat(markup)}`, - unit: 'percent', - }, - source_uuids: sources.map(src => src.uuid), - }) - .then(() => { - setSuccess(); - updateCostModel(); + <AccountSettings> + <Wizard + isOpen + title={intl.formatMessage(messages.CreateCostModelTitle)} + description={intl.formatMessage(messages.CreateCostModelDesc)} + steps={newSteps} + startAtStep={current} + onNext={onMove} + onBack={onMove} + onGoToStep={onMove} + onClose={closeFnc} + footer={isSuccess || isProcess || isAddingRate ? <div /> : null} + onSave={() => { + const { name, type, tiers, markup, description, distribution, isDiscount, sources } = context; + addCostModel({ + name, + source_type: type, + description, + distribution, + rates: transformTiers(tiers, 'USD', true), // Todo: Temporarily transform to USD for APIs, + markup: { + value: `${isDiscount ? '-' : ''}${unFormat(markup)}`, + unit: 'percent', + }, + source_uuids: sources.map(src => src.uuid), }) - .catch(err => setError(parseApiError(err))); - }} - /> + .then(() => { + setSuccess(); + updateCostModel(); + }) + .catch(err => setError(parseApiError(err))); + }} + /> + </AccountSettings> ) : null; }; From 700d41908e51b2ba7aac25961fd58a28293275f1 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:48:05 -0500 Subject: [PATCH 14/29] Replace cost-type with account-settings API https://issues.redhat.com/browse/COST-2201 --- src/api/accountSettings.ts | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/api/accountSettings.ts b/src/api/accountSettings.ts index a2d5ce682..be021594b 100644 --- a/src/api/accountSettings.ts +++ b/src/api/accountSettings.ts @@ -1,29 +1,25 @@ import axios from 'axios'; -import { PagedResponse } from './api'; +import { PagedLinks, PagedMetaData } from './api'; -// To do: Adjust when account-settings API is available export interface AccountSettingsData { - code?: string; - description?: string; - name?: string; -} - -export interface AccountSettingsMeta { - count?: string; - ['cost-type']?: string; + cost_type?: string; currency?: string; } -export interface AccountSettings extends PagedResponse<AccountSettingsData, AccountSettingsMeta> {} +export interface AccountSettings { + meta: PagedMetaData; + links?: PagedLinks; + data: AccountSettingsData; +} export function fetchAccountSettings() { const insights = (window as any).insights; if (insights && insights.chrome && insights.chrome.auth && insights.chrome.auth.getUser) { return insights.chrome.auth.getUser().then(() => { - return axios.get<AccountSettings>(`cost-type/`); // To do: Use account-settings API when available + return axios.get<AccountSettings>(`account-settings/`); }); } else { - return axios.get<AccountSettings>(`cost-type/`); // To do: Use account-settings API when available + return axios.get<AccountSettings>(`account-settings/`); } } From a3d90b8c5cf9caa304efbab4f90bdffa4f2c3780 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 12:56:04 -0500 Subject: [PATCH 15/29] Cleaned up comments --- src/components/accountSettings/accountSettings.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/accountSettings/accountSettings.tsx b/src/components/accountSettings/accountSettings.tsx index aac3c56de..8203864db 100644 --- a/src/components/accountSettings/accountSettings.tsx +++ b/src/components/accountSettings/accountSettings.tsx @@ -52,7 +52,6 @@ class AccountSettingsBase extends React.Component<AccountSettingsProps> { const { accountSettings } = this.props; if (prevProps.accountSettings !== accountSettings) { - // To do: Adjust meta properties when account-settings API is available const costType = accountSettings ? accountSettings.data.cost_type : CostTypes.unblended; const currency = accountSettings ? accountSettings.data.currency : 'USD'; From 3face900c6bc40f12be322c9e1a8e2638ae05555 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 14:33:33 -0500 Subject: [PATCH 16/29] Remove empty type param from user-access API request https://issues.redhat.com/browse/COST-1790 --- src/api/userAccess.ts | 2 +- src/store/userAccess/index.ts | 4 ++-- src/store/userAccess/userAccessCommon.ts | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/api/userAccess.ts b/src/api/userAccess.ts index 6c853e619..77bb7ea33 100644 --- a/src/api/userAccess.ts +++ b/src/api/userAccess.ts @@ -15,7 +15,7 @@ export interface UserAccess { // eslint-disable-next-line no-shadow export const enum UserAccessType { - all = '', + all = 'all', aws = 'aws', azure = 'azure', cost_model = 'cost_model', diff --git a/src/store/userAccess/index.ts b/src/store/userAccess/index.ts index 3ecfb9651..472f97ec9 100644 --- a/src/store/userAccess/index.ts +++ b/src/store/userAccess/index.ts @@ -1,11 +1,11 @@ import { - allUserAccessQuery, awsUserAccessQuery, azureUserAccessQuery, costModelUserAccessQuery, gcpUserAccessQuery, ibmUserAccessQuery, ocpUserAccessQuery, + userAccessQuery, } from 'store/userAccess/userAccessCommon'; import * as userAccessActions from './userAccessActions'; @@ -14,7 +14,7 @@ import { UserAccessAction, userAccessReducer, UserAccessState } from './userAcce import * as userAccessSelectors from './userAccessSelectors'; export { - allUserAccessQuery, + userAccessQuery, awsUserAccessQuery, azureUserAccessQuery, costModelUserAccessQuery, diff --git a/src/store/userAccess/userAccessCommon.ts b/src/store/userAccess/userAccessCommon.ts index 73c85e4f5..1f333e9c9 100644 --- a/src/store/userAccess/userAccessCommon.ts +++ b/src/store/userAccess/userAccessCommon.ts @@ -4,10 +4,6 @@ import { UserAccessType } from 'api/userAccess'; export const stateKey = 'userAccess'; export const userAccessKey = 'user-access'; -export const allUserAccessQuery: UserAccessQuery = { - type: '', -}; - export const awsUserAccessQuery: UserAccessQuery = { type: 'AWS', }; @@ -33,6 +29,9 @@ export const ibmUserAccessQuery: UserAccessQuery = { beta: true, }; +// Omitting the type param returns all user access +export const userAccessQuery: UserAccessQuery = {}; + export function getReportId(type: UserAccessType, query: string) { return `${type}--${query}`; } From efecc731147f1089ee9786cd143b85378546b7ab Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 14:35:50 -0500 Subject: [PATCH 17/29] Removed type param from user access API request --- src/components/accountSettings/accountSettings.tsx | 4 ++-- src/components/async/permissionsComponent/permissions.tsx | 4 ++-- src/modules/ocpOverviewWidget/ocpOverviewWidget.tsx | 4 ++-- src/pages/views/explorer/explorer.tsx | 4 ++-- src/pages/views/explorer/explorerHeader.tsx | 4 ++-- src/pages/views/overview/overview.tsx | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/accountSettings/accountSettings.tsx b/src/components/accountSettings/accountSettings.tsx index 8203864db..604e1aea4 100644 --- a/src/components/accountSettings/accountSettings.tsx +++ b/src/components/accountSettings/accountSettings.tsx @@ -7,7 +7,7 @@ import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { accountSettingsActions, accountSettingsSelectors } from 'store/accountSettings'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { allUserAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { CostTypes } from 'utils/localStorage'; interface AccountSettingsOwnProps { @@ -83,7 +83,7 @@ const mapStateToProps = createMapStateToProps<AccountSettingsOwnProps, AccountSe const accountSettingsError = accountSettingsSelectors.selectAccountSettingsError(state); const accountSettingsFetchStatus = accountSettingsSelectors.selectAccountSettingsFetchStatus(state); - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( diff --git a/src/components/async/permissionsComponent/permissions.tsx b/src/components/async/permissionsComponent/permissions.tsx index 91bfd5342..7ec66852d 100644 --- a/src/components/async/permissionsComponent/permissions.tsx +++ b/src/components/async/permissionsComponent/permissions.tsx @@ -9,7 +9,7 @@ import { connect } from 'react-redux'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import { paths, routes } from 'routes'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { allUserAccessQuery, ibmUserAccessQuery, userAccessActions, userAccessSelectors } from 'store/userAccess'; +import { ibmUserAccessQuery, userAccessActions, userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { hasAwsAccess, hasAzureAccess, @@ -127,7 +127,7 @@ class PermissionsBase extends React.Component<PermissionsProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<PermissionsOwnProps, PermissionsStateProps>((state, props) => { - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( diff --git a/src/modules/ocpOverviewWidget/ocpOverviewWidget.tsx b/src/modules/ocpOverviewWidget/ocpOverviewWidget.tsx index 7207521de..c114b640c 100644 --- a/src/modules/ocpOverviewWidget/ocpOverviewWidget.tsx +++ b/src/modules/ocpOverviewWidget/ocpOverviewWidget.tsx @@ -13,7 +13,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { createMapStateToProps, FetchStatus } from 'store/common'; import { ocpProvidersQuery, providersActions, providersSelectors } from 'store/providers'; -import { allUserAccessQuery, userAccessActions, userAccessSelectors } from 'store/userAccess'; +import { userAccessActions, userAccessQuery, userAccessSelectors } from 'store/userAccess'; import OcpOverviewChart from './ocpOverviewChart'; import { baseQuery, isOcpAvailable } from './ocpOverviewUtils'; @@ -132,7 +132,7 @@ const mapStateToProps = createMapStateToProps<OcpOverviewWidgetOwnProps, OcpOver providersQueryString ); - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( diff --git a/src/pages/views/explorer/explorer.tsx b/src/pages/views/explorer/explorer.tsx index 4d4e5c4b6..eb9592854 100644 --- a/src/pages/views/explorer/explorer.tsx +++ b/src/pages/views/explorer/explorer.tsx @@ -31,7 +31,7 @@ import { } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { uiActions } from 'store/ui'; -import { allUserAccessQuery, ibmUserAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { ibmUserAccessQuery, userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedExplorerReportItems'; import { ComputedReportItem, getUnsortedComputedReportItems } from 'utils/computedReport/getComputedReportItems'; import { isAwsAvailable, isAzureAvailable, isGcpAvailable, isIbmAvailable, isOcpAvailable } from 'utils/userAccess'; @@ -542,7 +542,7 @@ class Explorer extends React.Component<ExplorerProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<ExplorerOwnProps, ExplorerStateProps>((state, props) => { - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( diff --git a/src/pages/views/explorer/explorerHeader.tsx b/src/pages/views/explorer/explorerHeader.tsx index 18f1b57ee..5c99863c9 100644 --- a/src/pages/views/explorer/explorerHeader.tsx +++ b/src/pages/views/explorer/explorerHeader.tsx @@ -24,7 +24,7 @@ import { ocpProvidersQuery, providersSelectors, } from 'store/providers'; -import { allUserAccessQuery, ibmUserAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { ibmUserAccessQuery, userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedExplorerReportItems'; import { getLast60DaysDate } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; @@ -360,7 +360,7 @@ const mapStateToProps = createMapStateToProps<ExplorerHeaderOwnProps, ExplorerHe const dateRange = getDateRangeDefault(queryFromRoute); const { end_date, start_date } = getDateRange(getDateRangeDefault(queryFromRoute)); - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( diff --git a/src/pages/views/overview/overview.tsx b/src/pages/views/overview/overview.tsx index bbe0e1f10..53311ade5 100644 --- a/src/pages/views/overview/overview.tsx +++ b/src/pages/views/overview/overview.tsx @@ -56,7 +56,7 @@ import { providersSelectors, } from 'store/providers'; import { uiActions } from 'store/ui'; -import { allUserAccessQuery, ibmUserAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { ibmUserAccessQuery, userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { getSinceDateRangeString } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; import { getCostType } from 'utils/localStorage'; @@ -767,7 +767,7 @@ const mapStateToProps = createMapStateToProps<OverviewOwnProps, OverviewStatePro ocpProvidersQueryString ); - const userAccessQueryString = getUserAccessQuery(allUserAccessQuery); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); const userAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( From c205876ec12febc3dfa3d9a60217cd193f6f1ac4 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 14:36:55 -0500 Subject: [PATCH 18/29] Added Providers.all to fetch sources using one API request https://issues.redhat.com/browse/COST-2202 --- src/api/providers.ts | 1 + .../inactiveSources/inactiveSources.tsx | 295 ++---------------- src/store/providers/index.ts | 2 + src/store/providers/providersCommon.ts | 5 + 4 files changed, 41 insertions(+), 262 deletions(-) diff --git a/src/api/providers.ts b/src/api/providers.ts index 143e4646f..32314391b 100644 --- a/src/api/providers.ts +++ b/src/api/providers.ts @@ -56,6 +56,7 @@ export interface Providers extends PagedResponse<Provider, PagedMetaData> {} // eslint-disable-next-line no-shadow export const enum ProviderType { + all = 'all', aws = 'aws', azure = 'azure', gcp = 'gcp', diff --git a/src/components/inactiveSources/inactiveSources.tsx b/src/components/inactiveSources/inactiveSources.tsx index bd16584e9..12c01d651 100644 --- a/src/components/inactiveSources/inactiveSources.tsx +++ b/src/components/inactiveSources/inactiveSources.tsx @@ -9,15 +9,7 @@ import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { - awsProvidersQuery, - azureProvidersQuery, - gcpProvidersQuery, - ibmProvidersQuery, - ocpProvidersQuery, - providersActions, - providersSelectors, -} from 'store/providers'; +import { providersActions, providersQuery, providersSelectors } from 'store/providers'; import { deleteInactiveSources, invalidateInactiveSources, @@ -31,26 +23,10 @@ interface InactiveSourcesOwnProps { } interface InactiveSourcesStateProps { - awsProviders: Providers; - awsProvidersError: AxiosError; - awsProvidersFetchStatus: FetchStatus; - awsProvidersQueryString: string; - azureProviders: Providers; - azureProvidersError: AxiosError; - azureProvidersFetchStatus: FetchStatus; - azureProvidersQueryString: string; - gcpProviders: Providers; - gcpProvidersError: AxiosError; - gcpProvidersFetchStatus: FetchStatus; - gcpProvidersQueryString: string; - ibmProviders: Providers; - ibmProvidersError: AxiosError; - ibmProvidersFetchStatus: FetchStatus; - ibmProvidersQueryString: string; - ocpProviders: Providers; - ocpProvidersError: AxiosError; - ocpProvidersFetchStatus: FetchStatus; - ocpProvidersQueryString: string; + providers: Providers; + providersError: AxiosError; + providersFetchStatus: FetchStatus; + providersQueryString: string; } interface InactiveSourcesDispatchProps { @@ -73,130 +49,33 @@ class InactiveSourcesBase extends React.Component<InactiveSourcesProps> { public state: InactiveSourcesState = { ...this.defaultState }; public componentDidMount() { - const { - awsProviders, - awsProvidersFetchStatus, - azureProviders, - azureProvidersFetchStatus, - gcpProviders, - gcpProvidersFetchStatus, - ibmProviders, - ibmProvidersFetchStatus, - ocpProviders, - ocpProvidersFetchStatus, - } = this.props; + const { providers, providersFetchStatus } = this.props; - if (!awsProviders && awsProvidersFetchStatus !== FetchStatus.inProgress) { - this.fetchAwsProviders(); - } - if (!azureProviders && azureProvidersFetchStatus !== FetchStatus.inProgress) { - this.fetchAzureProviders(); - } - if (!gcpProviders && gcpProvidersFetchStatus !== FetchStatus.inProgress) { - this.fetchGcpProviders(); - } - if (!ibmProviders && ibmProvidersFetchStatus !== FetchStatus.inProgress) { - this.fetchIbmProviders(); - } - if (!ocpProviders && ocpProvidersFetchStatus !== FetchStatus.inProgress) { - this.fetchOcpProviders(); + if (!providers && providersFetchStatus !== FetchStatus.inProgress) { + this.fetchProviders(); } } public componentDidUpdate() { - const { - awsProviders, - awsProvidersError, - awsProvidersFetchStatus, - azureProviders, - azureProvidersError, - azureProvidersFetchStatus, - gcpProviders, - gcpProvidersFetchStatus, - ibmProviders, - ibmProvidersFetchStatus, - ocpProviders, - ocpProvidersError, - ocpProvidersFetchStatus, - } = this.props; + const { providers, providersError, providersFetchStatus } = this.props; - if (!awsProviders && awsProvidersFetchStatus !== FetchStatus.inProgress && !awsProvidersError) { - this.fetchAwsProviders(); - } - if (!azureProviders && azureProvidersFetchStatus !== FetchStatus.inProgress && !azureProvidersError) { - this.fetchAzureProviders(); - } - if (!gcpProviders && gcpProvidersFetchStatus !== FetchStatus.inProgress) { - this.fetchGcpProviders(); - } - if (!ibmProviders && ibmProvidersFetchStatus !== FetchStatus.inProgress) { - this.fetchIbmProviders(); - } - if (!ocpProviders && ocpProvidersFetchStatus !== FetchStatus.inProgress && !ocpProvidersError) { - this.fetchOcpProviders(); + if (!providers && providersFetchStatus !== FetchStatus.inProgress && !providersError) { + this.fetchProviders(); } } - private fetchAwsProviders = () => { - const { awsProvidersQueryString, fetchProviders } = this.props; - fetchProviders(ProviderType.aws, awsProvidersQueryString); - }; - - private fetchAzureProviders = () => { - const { azureProvidersQueryString, fetchProviders } = this.props; - fetchProviders(ProviderType.azure, azureProvidersQueryString); - }; - - private fetchGcpProviders = () => { - const { gcpProvidersQueryString, fetchProviders } = this.props; - fetchProviders(ProviderType.gcp, gcpProvidersQueryString); - }; - - private fetchIbmProviders = () => { - const { ibmProvidersQueryString, fetchProviders } = this.props; - fetchProviders(ProviderType.ibm, ibmProvidersQueryString); - }; - - private fetchOcpProviders = () => { - const { fetchProviders, ocpProvidersQueryString } = this.props; - fetchProviders(ProviderType.ocp, ocpProvidersQueryString); + private fetchProviders = () => { + const { fetchProviders, providersQueryString } = this.props; + fetchProviders(ProviderType.all, providersQueryString); }; private getInactiveSourceNames = () => { - const { awsProviders, azureProviders, gcpProviders, ibmProviders, ocpProviders } = this.props; + const { providers } = this.props; const sources = []; - if (awsProviders && awsProviders.data) { - awsProviders.data.map(data => { - if (data.active !== true) { - sources.push(data.name); - } - }); - } - if (azureProviders && azureProviders.data) { - azureProviders.data.map(data => { - if (data.active !== true) { - sources.push(data.name); - } - }); - } - if (gcpProviders && gcpProviders.data) { - gcpProviders.data.map(data => { - if (data.active !== true) { - sources.push(data.name); - } - }); - } - if (ibmProviders && ibmProviders.data) { - ibmProviders.data.map(data => { - if (data.active !== true) { - sources.push(data.name); - } - }); - } - if (ocpProviders && ocpProviders.data) { - ocpProviders.data.map(data => { + if (providers && providers.data) { + providers.data.map(data => { if (data.active !== true) { sources.push(data.name); } @@ -233,24 +112,7 @@ class InactiveSourcesBase extends React.Component<InactiveSourcesProps> { }; public render() { - const { - awsProviders, - awsProvidersError, - awsProvidersFetchStatus, - azureProviders, - azureProvidersError, - azureProvidersFetchStatus, - gcpProviders, - gcpProvidersError, - gcpProvidersFetchStatus, - ibmProviders, - ibmProvidersError, - ibmProvidersFetchStatus, - ocpProviders, - ocpProvidersError, - ocpProvidersFetchStatus, - intl, - } = this.props; + const { providers, providersError, providersFetchStatus, intl } = this.props; const release = getReleasePath(); const names = this.getInactiveSourceNames(); @@ -260,23 +122,7 @@ class InactiveSourcesBase extends React.Component<InactiveSourcesProps> { : intl.formatMessage(messages.InactiveSourcesTitleMultiplier); if (names.length === 0) { - if ( - awsProviders && - awsProvidersFetchStatus === FetchStatus.complete && - !awsProvidersError && - azureProviders && - azureProvidersFetchStatus === FetchStatus.complete && - !azureProvidersError && - gcpProviders && - gcpProvidersFetchStatus === FetchStatus.complete && - !gcpProvidersError && - ibmProviders && - ibmProvidersFetchStatus === FetchStatus.complete && - !ibmProvidersError && - ocpProviders && - ocpProvidersFetchStatus === FetchStatus.complete && - !ocpProvidersError - ) { + if (providers && providersFetchStatus === FetchStatus.complete && !providersError) { deleteInactiveSources(); // Reset cookie for new alerts } return null; @@ -310,109 +156,34 @@ class InactiveSourcesBase extends React.Component<InactiveSourcesProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<InactiveSourcesOwnProps, InactiveSourcesStateProps>((state, props) => { - const awsProvidersQueryString = getProvidersQuery(awsProvidersQuery); - const awsProviders = providersSelectors.selectProviders(state, ProviderType.aws, awsProvidersQueryString); - const awsProvidersError = providersSelectors.selectProvidersError(state, ProviderType.aws, awsProvidersQueryString); - const awsProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.aws, - awsProvidersQueryString - ); - - const azureProvidersQueryString = getProvidersQuery(azureProvidersQuery); - const azureProviders = providersSelectors.selectProviders(state, ProviderType.azure, azureProvidersQueryString); - const azureProvidersError = providersSelectors.selectProvidersError( - state, - ProviderType.azure, - azureProvidersQueryString - ); - const azureProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.azure, - azureProvidersQueryString - ); - - const gcpProvidersQueryString = getProvidersQuery(gcpProvidersQuery); - const gcpProviders = providersSelectors.selectProviders(state, ProviderType.gcp, gcpProvidersQueryString); - const gcpProvidersError = providersSelectors.selectProvidersError(state, ProviderType.gcp, gcpProvidersQueryString); - const gcpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); + const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.gcp, - gcpProvidersQueryString - ); - - const ibmProvidersQueryString = getProvidersQuery(ibmProvidersQuery); - const ibmProviders = providersSelectors.selectProviders(state, ProviderType.ibm, ibmProvidersQueryString); - const ibmProvidersError = providersSelectors.selectProvidersError(state, ProviderType.ibm, ibmProvidersQueryString); - const ibmProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ibm, - ibmProvidersQueryString - ); - - const ocpProvidersQueryString = getProvidersQuery(ocpProvidersQuery); - const ocpProviders = providersSelectors.selectProviders(state, ProviderType.ocp, ocpProvidersQueryString); - const ocpProvidersError = providersSelectors.selectProvidersError(state, ProviderType.ocp, ocpProvidersQueryString); - const ocpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ocp, - ocpProvidersQueryString + ProviderType.all, + providersQueryString ); // For testing... // - // if (awsProviders && awsProviders.data) { - // if (awsProviders.data.length) { - // awsProviders.data[0].active = false; + // if (providers && providers.data) { + // if (providers.data.length) { + // providers.data[0].active = false; // } else { - // awsProviders.data[0] = { + // providers.data[0] = { // name: 'AWS for OpenShift', // active: false, // }; // } // } - // if (azureProviders && azureProviders.data) { - // if (azureProviders.data.length) { - // azureProviders.data[0].active = false; - // } else { - // azureProviders.data[0] = { - // name: 'Azure for OpenShift', - // active: false, - // }; - // } - // } - // if (ocpProviders && ocpProviders.data) { - // if (ocpProviders.data.length) { - // ocpProviders.data[0].active = false; - // } else { - // ocpProviders.data[0] = { - // name: 'OCP', - // active: false, - // }; - // } // } return { - awsProviders, - awsProvidersError, - awsProvidersFetchStatus, - awsProvidersQueryString, - azureProviders, - azureProvidersError, - azureProvidersFetchStatus, - azureProvidersQueryString, - gcpProviders, - gcpProvidersError, - gcpProvidersFetchStatus, - gcpProvidersQueryString, - ibmProviders, - ibmProvidersError, - ibmProvidersFetchStatus, - ibmProvidersQueryString, - ocpProviders, - ocpProvidersError, - ocpProvidersFetchStatus, - ocpProvidersQueryString, + providers, + providersError, + providersFetchStatus, + providersQueryString, }; }); diff --git a/src/store/providers/index.ts b/src/store/providers/index.ts index 45234eb7a..fa5ae3b83 100644 --- a/src/store/providers/index.ts +++ b/src/store/providers/index.ts @@ -4,6 +4,7 @@ import { gcpProvidersQuery, ibmProvidersQuery, ocpProvidersQuery, + providersQuery, } from 'store/providers/providersCommon'; import * as providersActions from './providersActions'; @@ -19,6 +20,7 @@ export { ocpProvidersQuery, ProvidersAction, providersActions, + providersQuery, providersReducer, providersSelectors, ProvidersState, diff --git a/src/store/providers/providersCommon.ts b/src/store/providers/providersCommon.ts index 542628fdc..b30b13e83 100644 --- a/src/store/providers/providersCommon.ts +++ b/src/store/providers/providersCommon.ts @@ -29,6 +29,11 @@ export const ocpProvidersQuery: ProvidersQuery = { type: 'OCP', }; +// Omitting the type param, returns all providers +export const providersQuery: ProvidersQuery = { + limit: 1000, +}; + export function getReportId(type: ProviderType, query: string) { return `${type}--${query}`; } From e999e85db40e3a1dbe617aba98fedb8897d046c7 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 18:08:22 -0500 Subject: [PATCH 19/29] Remove beta param for IBM user-access API --- .../permissionsComponent/permissions.tsx | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/components/async/permissionsComponent/permissions.tsx b/src/components/async/permissionsComponent/permissions.tsx index 7ec66852d..2b1819221 100644 --- a/src/components/async/permissionsComponent/permissions.tsx +++ b/src/components/async/permissionsComponent/permissions.tsx @@ -9,7 +9,7 @@ import { connect } from 'react-redux'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import { paths, routes } from 'routes'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { ibmUserAccessQuery, userAccessActions, userAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { userAccessActions, userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { hasAwsAccess, hasAzureAccess, @@ -24,10 +24,6 @@ interface PermissionsOwnProps extends RouteComponentProps<void> { } interface PermissionsStateProps { - ibmUserAccess: UserAccess; - ibmUserAccessError: AxiosError; - ibmUserAccessFetchStatus: FetchStatus; - ibmUserAccessQueryString: string; userAccess: UserAccess; userAccessError: AxiosError; userAccessFetchStatus: FetchStatus; @@ -51,10 +47,9 @@ class PermissionsBase extends React.Component<PermissionsProps> { public state: PermissionsState = { ...this.defaultState }; public componentDidMount() { - const { ibmUserAccessQueryString, userAccessQueryString, fetchUserAccess } = this.props; + const { userAccessQueryString, fetchUserAccess } = this.props; fetchUserAccess(UserAccessType.all, userAccessQueryString); - fetchUserAccess(UserAccessType.ibm, ibmUserAccessQueryString); } private getPath() { @@ -69,7 +64,7 @@ class PermissionsBase extends React.Component<PermissionsProps> { } private hasPermissions() { - const { ibmUserAccess, userAccess } = this.props; + const { userAccess } = this.props; if (!userAccess) { return false; @@ -79,7 +74,7 @@ class PermissionsBase extends React.Component<PermissionsProps> { const azure = hasAzureAccess(userAccess); const costModel = hasCostModelAccess(userAccess); const gcp = hasGcpAccess(userAccess); - const ibm = hasIbmAccess(ibmUserAccess); + const ibm = hasIbmAccess(userAccess); const ocp = hasOcpAccess(userAccess); const path = this.getPath(); @@ -136,25 +131,7 @@ const mapStateToProps = createMapStateToProps<PermissionsOwnProps, PermissionsSt userAccessQueryString ); - // Todo: temporarily request IBM separately with beta flag. - const ibmUserAccessQueryString = getUserAccessQuery(ibmUserAccessQuery); - const ibmUserAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.ibm, ibmUserAccessQueryString); - const ibmUserAccessError = userAccessSelectors.selectUserAccessError( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - const ibmUserAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - return { - ibmUserAccess, - ibmUserAccessError, - ibmUserAccessFetchStatus, - ibmUserAccessQueryString, userAccess, userAccessError, userAccessFetchStatus, From 532e5003b88a0b2b5af84ef76c117be134e8b8f9 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Fri, 14 Jan 2022 18:09:26 -0500 Subject: [PATCH 20/29] Modify overview to use a single API request instead of requesting individual source types https://issues.redhat.com/browse/COST-2202 --- src/api/providers.ts | 1 + src/pages/views/overview/overview.tsx | 175 +++++++------------------- src/pages/views/utils/providers.ts | 15 ++- 3 files changed, 61 insertions(+), 130 deletions(-) diff --git a/src/api/providers.ts b/src/api/providers.ts index 32314391b..7e45672b3 100644 --- a/src/api/providers.ts +++ b/src/api/providers.ts @@ -48,6 +48,7 @@ export interface Provider { infrastructure?: ProviderInfrastructure; name?: string; previous_month_data?: boolean; + source_type?: string; type?: string; uuid?: string; } diff --git a/src/pages/views/overview/overview.tsx b/src/pages/views/overview/overview.tsx index 53311ade5..c11b2d0b4 100644 --- a/src/pages/views/overview/overview.tsx +++ b/src/pages/views/overview/overview.tsx @@ -35,6 +35,7 @@ import IbmDashboard from 'pages/views/overview/ibmDashboard'; import OcpCloudDashboard from 'pages/views/overview/ocpCloudDashboard'; import OcpDashboard from 'pages/views/overview/ocpDashboard'; import { + filterProviders, hasCloudCurrentMonthData, hasCloudData, hasCloudPreviousMonthData, @@ -47,16 +48,9 @@ import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { - awsProvidersQuery, - azureProvidersQuery, - gcpProvidersQuery, - ibmProvidersQuery, - ocpProvidersQuery, - providersSelectors, -} from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { uiActions } from 'store/ui'; -import { ibmUserAccessQuery, userAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { getSinceDateRangeString } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; import { getCostType } from 'utils/localStorage'; @@ -113,25 +107,14 @@ interface OverviewDispatchProps { } interface OverviewStateProps { - awsProviders: Providers; - awsProvidersFetchStatus: FetchStatus; - awsProvidersQueryString: string; - azureProviders: Providers; - azureProvidersFetchStatus: FetchStatus; - azureProvidersQueryString: string; - gcpProviders: Providers; - gcpProvidersFetchStatus: FetchStatus; - gcpProvidersQueryString: string; - ibmProviders: Providers; - ibmProvidersFetchStatus: FetchStatus; - ibmProvidersQueryString: string; - ibmUserAccess: UserAccess; - ibmUserAccessError: AxiosError; - ibmUserAccessFetchStatus: FetchStatus; - ibmUserAccessQueryString: string; - ocpProviders: Providers; - ocpProvidersFetchStatus: FetchStatus; - ocpProvidersQueryString: string; + awsProviders?: Providers; + azureProviders?: Providers; + gcpProviders?: Providers; + ibmProviders?: Providers; + ocpProviders?: Providers; + providers: Providers; + providersFetchStatus: FetchStatus; + providersQueryString: string; perspective?: string; query: OverviewQuery; queryString: string; @@ -205,17 +188,10 @@ class OverviewBase extends React.Component<OverviewProps> { } public componentDidUpdate(prevProps: OverviewProps) { - const { awsProviders, azureProviders, gcpProviders, ibmProviders, ocpProviders, tabKey, userAccess } = this.props; + const { providers, tabKey, userAccess } = this.props; // Note: User access and providers are fetched via the Permissions and InactiveSources components used by all routes - if ( - prevProps.userAccess !== userAccess || - prevProps.awsProviders !== awsProviders || - prevProps.azureProviders !== azureProviders || - prevProps.gcpProviders !== gcpProviders || - prevProps.ibmProviders !== ibmProviders || - prevProps.ocpProviders !== ocpProviders - ) { + if (prevProps.userAccess !== userAccess || prevProps.providers !== providers) { this.setState({ activeTabKey: tabKey, currentInfrastructurePerspective: this.getDefaultInfrastructurePerspective(), @@ -432,12 +408,14 @@ class OverviewBase extends React.Component<OverviewProps> { private getTabItem = (tab: OverviewTab, index: number) => { const { awsProviders, azureProviders, gcpProviders, ibmProviders, ocpProviders } = this.props; const { activeTabKey, costType, currentInfrastructurePerspective, currentOcpPerspective } = this.state; + const emptyTab = <></>; // Lazily load tabs const noData = <NoData showReload={false} />; if (activeTabKey !== index) { return emptyTab; } + const currentTab = getIdKeyForTab(tab); if (currentTab === OverviewTab.infrastructure) { if (currentInfrastructurePerspective === InfrastructurePerspective.ocpCloud) { @@ -565,46 +543,55 @@ class OverviewBase extends React.Component<OverviewProps> { private isAwsAvailable = () => { const { awsProviders, userAccess } = this.props; + return isAwsAvailable(userAccess, awsProviders); }; private isAwsCloudAvailable = () => { const { awsProviders, ocpProviders, userAccess } = this.props; + return hasAwsAccess(userAccess) && hasCloudProvider(awsProviders, ocpProviders); }; private isAzureAvailable = () => { const { azureProviders, userAccess } = this.props; + return isAzureAvailable(userAccess, azureProviders); }; private isAzureCloudAvailable = () => { const { azureProviders, ocpProviders, userAccess } = this.props; + return hasAzureAccess(userAccess) && hasCloudProvider(azureProviders, ocpProviders); }; private isGcpAvailable = () => { const { gcpProviders, userAccess } = this.props; + return isGcpAvailable(userAccess, gcpProviders); }; private isGcpCloudAvailable = () => { const { gcpProviders, ocpProviders, userAccess } = this.props; + return hasGcpAccess(userAccess) && hasCloudProvider(gcpProviders, ocpProviders); }; private isIbmAvailable = () => { - const { ibmProviders, ibmUserAccess } = this.props; - return isIbmAvailable(ibmUserAccess, ibmProviders); + const { ibmProviders, userAccess } = this.props; + + return isIbmAvailable(userAccess, ibmProviders); }; private isIbmCloudAvailable = () => { const { ibmProviders, ocpProviders, userAccess } = this.props; + return hasIbmAccess(userAccess) && hasCloudProvider(ibmProviders, ocpProviders); }; private isOcpAvailable = () => { const { ocpProviders, userAccess } = this.props; + return isOcpAvailable(userAccess, ocpProviders); }; @@ -618,31 +605,18 @@ class OverviewBase extends React.Component<OverviewProps> { }; public render() { - const { - awsProvidersFetchStatus, - azureProvidersFetchStatus, - gcpProvidersFetchStatus, - ibmProvidersFetchStatus, - intl, - ocpProvidersFetchStatus, - userAccessFetchStatus, - } = this.props; + const { providersFetchStatus, intl, userAccessFetchStatus } = this.props; // Note: No need to test OCP on cloud here, since that requires at least one provider - const noAwsProviders = !this.isAwsAvailable() && awsProvidersFetchStatus === FetchStatus.complete; - const noAzureProviders = !this.isAzureAvailable() && azureProvidersFetchStatus === FetchStatus.complete; - const noGcpProviders = !this.isGcpAvailable() && gcpProvidersFetchStatus === FetchStatus.complete; - const noIbmProviders = !this.isIbmAvailable() && ibmProvidersFetchStatus === FetchStatus.complete; - const noOcpProviders = !this.isOcpAvailable() && ocpProvidersFetchStatus === FetchStatus.complete; + const noAwsProviders = !this.isAwsAvailable() && providersFetchStatus === FetchStatus.complete; + const noAzureProviders = !this.isAzureAvailable() && providersFetchStatus === FetchStatus.complete; + const noGcpProviders = !this.isGcpAvailable() && providersFetchStatus === FetchStatus.complete; + const noIbmProviders = !this.isIbmAvailable() && providersFetchStatus === FetchStatus.complete; + const noOcpProviders = !this.isOcpAvailable() && providersFetchStatus === FetchStatus.complete; const noProviders = noAwsProviders && noAzureProviders && noGcpProviders && noIbmProviders && noOcpProviders; const isLoading = - awsProvidersFetchStatus === FetchStatus.inProgress || - azureProvidersFetchStatus === FetchStatus.inProgress || - gcpProvidersFetchStatus === FetchStatus.inProgress || - ibmProvidersFetchStatus === FetchStatus.inProgress || - ocpProvidersFetchStatus === FetchStatus.inProgress || - userAccessFetchStatus === FetchStatus.inProgress; + providersFetchStatus === FetchStatus.inProgress || userAccessFetchStatus === FetchStatus.inProgress; const availableTabs = this.getAvailableTabs(); const title = intl.formatMessage(messages.OverviewTitle); @@ -727,44 +701,12 @@ const mapStateToProps = createMapStateToProps<OverviewOwnProps, OverviewStatePro }; const queryString = getQuery(query); - const awsProvidersQueryString = getProvidersQuery(awsProvidersQuery); - const awsProviders = providersSelectors.selectProviders(state, ProviderType.aws, awsProvidersQueryString); - const awsProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.aws, - awsProvidersQueryString - ); - - const azureProvidersQueryString = getProvidersQuery(azureProvidersQuery); - const azureProviders = providersSelectors.selectProviders(state, ProviderType.azure, azureProvidersQueryString); - const azureProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.azure, - azureProvidersQueryString - ); - - const gcpProvidersQueryString = getProvidersQuery(gcpProvidersQuery); - const gcpProviders = providersSelectors.selectProviders(state, ProviderType.gcp, gcpProvidersQueryString); - const gcpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.gcp, - gcpProvidersQueryString - ); - - const ibmProvidersQueryString = getProvidersQuery(ibmProvidersQuery); - const ibmProviders = providersSelectors.selectProviders(state, ProviderType.ibm, ibmProvidersQueryString); - const ibmProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ibm, - ibmProvidersQueryString - ); - - const ocpProvidersQueryString = getProvidersQuery(ocpProvidersQuery); - const ocpProviders = providersSelectors.selectProviders(state, ProviderType.ocp, ocpProvidersQueryString); - const ocpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ocp, - ocpProvidersQueryString + ProviderType.all, + providersQueryString ); const userAccessQueryString = getUserAccessQuery(userAccessQuery); @@ -776,40 +718,15 @@ const mapStateToProps = createMapStateToProps<OverviewOwnProps, OverviewStatePro userAccessQueryString ); - // Todo: temporarily request IBM separately with beta flag. - const ibmUserAccessQueryString = getUserAccessQuery(ibmUserAccessQuery); - const ibmUserAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.ibm, ibmUserAccessQueryString); - const ibmUserAccessError = userAccessSelectors.selectUserAccessError( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - const ibmUserAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - return { - awsProviders, - awsProvidersFetchStatus, - awsProvidersQueryString, - azureProviders, - azureProvidersFetchStatus, - azureProvidersQueryString, - gcpProviders, - gcpProvidersFetchStatus, - gcpProvidersQueryString, - ibmProviders, - ibmProvidersFetchStatus, - ibmProvidersQueryString, - ibmUserAccess, - ibmUserAccessError, - ibmUserAccessFetchStatus, - ibmUserAccessQueryString, - ocpProviders, - ocpProvidersFetchStatus, - ocpProvidersQueryString, + awsProviders: filterProviders(providers, ProviderType.aws), + azureProviders: filterProviders(providers, ProviderType.azure), + gcpProviders: filterProviders(providers, ProviderType.gcp), + ibmProviders: filterProviders(providers, ProviderType.ibm), + ocpProviders: filterProviders(providers, ProviderType.ocp), + providers, + providersFetchStatus, + providersQueryString, perspective, query, queryString, diff --git a/src/pages/views/utils/providers.ts b/src/pages/views/utils/providers.ts index 5e6167ad8..ac23d7d1f 100644 --- a/src/pages/views/utils/providers.ts +++ b/src/pages/views/utils/providers.ts @@ -1,4 +1,4 @@ -import { Providers } from 'api/providers'; +import { Providers, ProviderType } from 'api/providers'; // eslint-disable-next-line no-shadow const enum DataType { @@ -22,6 +22,19 @@ const _getOcpProvider = (ocpProviders: Providers, uuid?: string) => { return result; }; +// Returns new Provider matching the given provider type +export const filterProviders = (providers: Providers, sourceType: ProviderType) => { + if (!providers) { + return providers; + } + + const data = providers.data.filter(provider => provider.source_type.toLowerCase() === sourceType); + return { + ...providers, + data, + } as Providers; +}; + // Ensure at least one source provider has data available const _hasData = (providers: Providers, dataType: DataType) => { let result = false; From 355a6a0cc4d87ba703c5154481bcc46672445614 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:20:11 -0500 Subject: [PATCH 21/29] Modified AWS details to use single source API request --- .../details/awsBreakdown/awsBreakdown.tsx | 18 ++++++++++++------ .../views/details/awsDetails/awsDetails.tsx | 15 +++++++++------ .../views/details/awsDetails/detailsHeader.tsx | 14 ++++++++------ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/pages/views/details/awsBreakdown/awsBreakdown.tsx b/src/pages/views/details/awsBreakdown/awsBreakdown.tsx index 4970fd616..59d184d98 100644 --- a/src/pages/views/details/awsBreakdown/awsBreakdown.tsx +++ b/src/pages/views/details/awsBreakdown/awsBreakdown.tsx @@ -1,4 +1,4 @@ -import { ProviderType } from 'api/providers'; +import { Providers, ProviderType } from 'api/providers'; import { AwsQuery, getQuery, parseQuery } from 'api/queries/awsQuery'; import { getProvidersQuery } from 'api/queries/providersQuery'; import { breakdownDescKey, breakdownTitleKey, logicalAndPrefix, orgUnitIdKey, Query } from 'api/queries/query'; @@ -8,12 +8,13 @@ import { AxiosError } from 'axios'; import messages from 'locales/messages'; import BreakdownBase from 'pages/views/details/components/breakdown/breakdownBase'; import { getGroupById, getGroupByOrgValue, getGroupByValue } from 'pages/views/utils/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { paths } from 'routes'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { awsProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { getCostType } from 'utils/localStorage'; @@ -26,6 +27,9 @@ interface AwsBreakdownStateProps { CostOverview?: React.ReactNode; detailsURL: string; HistoricalData?: React.ReactNode; + providers: Providers; + providersError: AxiosError; + providersFetchStatus: FetchStatus; query: Query; queryString: string; report: Report; @@ -73,11 +77,12 @@ const mapStateToProps = createMapStateToProps<AwsBreakdownOwnProps, AwsBreakdown const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(awsProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.aws, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.aws, + ProviderType.all, providersQueryString ); @@ -90,7 +95,8 @@ const mapStateToProps = createMapStateToProps<AwsBreakdownOwnProps, AwsBreakdown groupBy, groupByValue, historicalDataComponent: <HistoricalData costType={cost_type} />, - providers, + providers: filterProviders(providers, ProviderType.aws), + providersError, providersFetchStatus, providerType: ProviderType.aws, query, diff --git a/src/pages/views/details/awsDetails/awsDetails.tsx b/src/pages/views/details/awsDetails/awsDetails.tsx index 15ebda4e1..3e280c90e 100644 --- a/src/pages/views/details/awsDetails/awsDetails.tsx +++ b/src/pages/views/details/awsDetails/awsDetails.tsx @@ -13,14 +13,14 @@ import NoProviders from 'pages/state/noProviders'; import NotAvailable from 'pages/state/notAvailable'; import { ExportModal } from 'pages/views/components/export/exportModal'; import { getGroupByTagKey } from 'pages/views/utils/groupBy'; -import { hasCurrentMonthData } from 'pages/views/utils/providers'; +import { filterProviders, hasCurrentMonthData } from 'pages/views/utils/providers'; import { addQueryFilter, removeQueryFilter } from 'pages/views/utils/query'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { awsProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { uiActions } from 'store/ui'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedAwsReportItems'; @@ -34,6 +34,7 @@ import { DetailsToolbar } from './detailsToolbar'; interface AwsDetailsStateProps { providers: Providers; + providersError: AxiosError; providersFetchStatus: FetchStatus; query: AwsQuery; queryString: string; @@ -468,16 +469,18 @@ const mapStateToProps = createMapStateToProps<AwsDetailsOwnProps, AwsDetailsStat const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(awsProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.aws, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.aws, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.aws), + providersError, providersFetchStatus, query, queryString, diff --git a/src/pages/views/details/awsDetails/detailsHeader.tsx b/src/pages/views/details/awsDetails/detailsHeader.tsx index b2d90145c..4068073ec 100644 --- a/src/pages/views/details/awsDetails/detailsHeader.tsx +++ b/src/pages/views/details/awsDetails/detailsHeader.tsx @@ -10,11 +10,12 @@ import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { CostType } from 'pages/views/components/costType'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { awsProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { ComputedAwsReportItemsParams, getIdKeyForGroupBy } from 'utils/computedReport/getComputedAwsReportItems'; import { getSinceDateRangeString } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; @@ -121,17 +122,18 @@ class DetailsHeaderBase extends React.Component<DetailsHeaderProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<DetailsHeaderOwnProps, DetailsHeaderStateProps>((state, props) => { const queryString = getQuery(baseQuery); - const providersQueryString = getProvidersQuery(awsProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.aws, providersQueryString); - const providersError = providersSelectors.selectProvidersError(state, ProviderType.aws, providersQueryString); + + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.aws, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.aws), providersError, providersFetchStatus, queryString, From 35082f2c0d1a1d33453905793edeb2bfed0912e2 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:20:35 -0500 Subject: [PATCH 22/29] Modified Azure details to use single source API request --- .../details/azureBreakdown/azureBreakdown.tsx | 18 ++++++++++++------ .../details/azureDetails/azureDetails.tsx | 15 +++++++++------ .../details/azureDetails/detailsHeader.tsx | 14 ++++++++------ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/pages/views/details/azureBreakdown/azureBreakdown.tsx b/src/pages/views/details/azureBreakdown/azureBreakdown.tsx index 9baf11da4..623425c00 100644 --- a/src/pages/views/details/azureBreakdown/azureBreakdown.tsx +++ b/src/pages/views/details/azureBreakdown/azureBreakdown.tsx @@ -1,4 +1,4 @@ -import { ProviderType } from 'api/providers'; +import { Providers, ProviderType } from 'api/providers'; import { getQuery, OcpQuery, parseQuery } from 'api/queries/ocpQuery'; import { getProvidersQuery } from 'api/queries/providersQuery'; import { breakdownDescKey, Query } from 'api/queries/query'; @@ -8,12 +8,13 @@ import { AxiosError } from 'axios'; import messages from 'locales/messages'; import BreakdownBase from 'pages/views/details/components/breakdown/breakdownBase'; import { getGroupById, getGroupByValue } from 'pages/views/utils/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { paths } from 'routes'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { azureProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { CostOverview } from './costOverview'; @@ -25,6 +26,9 @@ interface AzureCostStateProps { CostOverview?: React.ReactNode; detailsURL: string; HistoricalData?: React.ReactNode; + providers: Providers; + providersError: AxiosError; + providersFetchStatus: FetchStatus; query: Query; queryString: string; report: Report; @@ -69,11 +73,12 @@ const mapStateToProps = createMapStateToProps<AzureCostOwnProps, AzureCostStateP const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(azureProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.azure, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.azure, + ProviderType.all, providersQueryString ); @@ -85,7 +90,8 @@ const mapStateToProps = createMapStateToProps<AzureCostOwnProps, AzureCostStateP groupBy, groupByValue, historicalDataComponent: <HistoricalData />, - providers, + providers: filterProviders(providers, ProviderType.azure), + providersError, providersFetchStatus, providerType: ProviderType.azure, query, diff --git a/src/pages/views/details/azureDetails/azureDetails.tsx b/src/pages/views/details/azureDetails/azureDetails.tsx index 1551b1b2e..172591b03 100644 --- a/src/pages/views/details/azureDetails/azureDetails.tsx +++ b/src/pages/views/details/azureDetails/azureDetails.tsx @@ -13,14 +13,14 @@ import NoProviders from 'pages/state/noProviders'; import NotAvailable from 'pages/state/notAvailable'; import { ExportModal } from 'pages/views/components/export/exportModal'; import { getGroupByTagKey } from 'pages/views/utils/groupBy'; -import { hasCurrentMonthData } from 'pages/views/utils/providers'; +import { filterProviders, hasCurrentMonthData } from 'pages/views/utils/providers'; import { addQueryFilter, removeQueryFilter } from 'pages/views/utils/query'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { azureProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { uiActions } from 'store/ui'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedAzureReportItems'; @@ -33,6 +33,7 @@ import { DetailsToolbar } from './detailsToolbar'; interface AzureDetailsStateProps { providers: Providers; + providersError: AxiosError; providersFetchStatus: FetchStatus; query: AzureQuery; queryString: string; @@ -437,16 +438,18 @@ const mapStateToProps = createMapStateToProps<AzureDetailsOwnProps, AzureDetails const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(azureProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.azure, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.azure, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.azure), + providersError, providersFetchStatus, query, queryString, diff --git a/src/pages/views/details/azureDetails/detailsHeader.tsx b/src/pages/views/details/azureDetails/detailsHeader.tsx index a6a8073f3..ab6fbf705 100644 --- a/src/pages/views/details/azureDetails/detailsHeader.tsx +++ b/src/pages/views/details/azureDetails/detailsHeader.tsx @@ -8,11 +8,12 @@ import { AxiosError } from 'axios'; import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { azureProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { ComputedAzureReportItemsParams, getIdKeyForGroupBy } from 'utils/computedReport/getComputedAzureReportItems'; import { getSinceDateRangeString } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; @@ -104,17 +105,18 @@ class DetailsHeaderBase extends React.Component<DetailsHeaderProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<DetailsHeaderOwnProps, DetailsHeaderStateProps>((state, props) => { const queryString = getQuery(baseQuery); - const providersQueryString = getProvidersQuery(azureProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.azure, providersQueryString); - const providersError = providersSelectors.selectProvidersError(state, ProviderType.azure, providersQueryString); + + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.azure, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.azure), providersError, providersFetchStatus, queryString, From 6386b3cb9c7f1c64a2ea5e036eeca2cf05aa461c Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:21:06 -0500 Subject: [PATCH 23/29] Modified GCP details to use single source API request --- .../details/gcpBreakdown/gcpBreakdown.tsx | 18 ++++++++++++------ .../views/details/gcpDetails/detailsHeader.tsx | 14 ++++++++------ .../views/details/gcpDetails/gcpDetails.tsx | 15 +++++++++------ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/pages/views/details/gcpBreakdown/gcpBreakdown.tsx b/src/pages/views/details/gcpBreakdown/gcpBreakdown.tsx index ed998f77c..14747f5b8 100644 --- a/src/pages/views/details/gcpBreakdown/gcpBreakdown.tsx +++ b/src/pages/views/details/gcpBreakdown/gcpBreakdown.tsx @@ -1,4 +1,4 @@ -import { ProviderType } from 'api/providers'; +import { Providers, ProviderType } from 'api/providers'; import { GcpQuery, getQuery, parseQuery } from 'api/queries/gcpQuery'; import { getProvidersQuery } from 'api/queries/providersQuery'; import { breakdownDescKey, breakdownTitleKey, Query } from 'api/queries/query'; @@ -8,12 +8,13 @@ import { AxiosError } from 'axios'; import messages from 'locales/messages'; import BreakdownBase from 'pages/views/details/components/breakdown/breakdownBase'; import { getGroupById, getGroupByValue } from 'pages/views/utils/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { paths } from 'routes'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { gcpProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { CostOverview } from './costOverview'; @@ -25,6 +26,9 @@ interface GcpBreakdownStateProps { CostOverview?: React.ReactNode; detailsURL: string; HistoricalData?: React.ReactNode; + providers: Providers; + providersError: AxiosError; + providersFetchStatus: FetchStatus; query: Query; queryString: string; report: Report; @@ -69,11 +73,12 @@ const mapStateToProps = createMapStateToProps<GcpBreakdownOwnProps, GcpBreakdown const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(gcpProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.gcp, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.gcp, + ProviderType.all, providersQueryString ); @@ -85,7 +90,8 @@ const mapStateToProps = createMapStateToProps<GcpBreakdownOwnProps, GcpBreakdown groupBy, groupByValue, historicalDataComponent: <HistoricalData />, - providers, + providers: filterProviders(providers, ProviderType.gcp), + providersError, providersFetchStatus, providerType: ProviderType.gcp, query, diff --git a/src/pages/views/details/gcpDetails/detailsHeader.tsx b/src/pages/views/details/gcpDetails/detailsHeader.tsx index 2cf198ffa..573ceb73e 100644 --- a/src/pages/views/details/gcpDetails/detailsHeader.tsx +++ b/src/pages/views/details/gcpDetails/detailsHeader.tsx @@ -8,11 +8,12 @@ import { AxiosError } from 'axios'; import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { gcpProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { ComputedGcpReportItemsParams, getIdKeyForGroupBy } from 'utils/computedReport/getComputedGcpReportItems'; import { getSinceDateRangeString } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; @@ -105,17 +106,18 @@ class DetailsHeaderBase extends React.Component<DetailsHeaderProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<DetailsHeaderOwnProps, DetailsHeaderStateProps>((state, props) => { const queryString = getQuery(baseQuery); - const providersQueryString = getProvidersQuery(gcpProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.gcp, providersQueryString); - const providersError = providersSelectors.selectProvidersError(state, ProviderType.gcp, providersQueryString); + + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.gcp, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.gcp), providersError, providersFetchStatus, queryString, diff --git a/src/pages/views/details/gcpDetails/gcpDetails.tsx b/src/pages/views/details/gcpDetails/gcpDetails.tsx index 2fe46703a..e74d0bdb2 100644 --- a/src/pages/views/details/gcpDetails/gcpDetails.tsx +++ b/src/pages/views/details/gcpDetails/gcpDetails.tsx @@ -13,14 +13,14 @@ import NoProviders from 'pages/state/noProviders'; import NotAvailable from 'pages/state/notAvailable'; import { ExportModal } from 'pages/views/components/export/exportModal'; import { getGroupByTagKey } from 'pages/views/utils/groupBy'; -import { hasCurrentMonthData } from 'pages/views/utils/providers'; +import { filterProviders, hasCurrentMonthData } from 'pages/views/utils/providers'; import { addQueryFilter, removeQueryFilter } from 'pages/views/utils/query'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { gcpProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { uiActions } from 'store/ui'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedGcpReportItems'; @@ -33,6 +33,7 @@ import { styles } from './gcpDetails.styles'; interface GcpDetailsStateProps { providers: Providers; + providersError: AxiosError; providersFetchStatus: FetchStatus; query: GcpQuery; queryString: string; @@ -436,16 +437,18 @@ const mapStateToProps = createMapStateToProps<GcpDetailsOwnProps, GcpDetailsStat const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(gcpProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.gcp, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.gcp, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.gcp), + providersError, providersFetchStatus, query, queryString, From 06fbba520399f281d93e4218aa6adff8866a2bfa Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:21:32 -0500 Subject: [PATCH 24/29] Modified IBM details to use single source API request --- .../details/ibmBreakdown/ibmBreakdown.tsx | 18 ++++++++++++------ .../views/details/ibmDetails/detailsHeader.tsx | 14 ++++++++------ .../views/details/ibmDetails/ibmDetails.tsx | 14 +++++++++----- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/pages/views/details/ibmBreakdown/ibmBreakdown.tsx b/src/pages/views/details/ibmBreakdown/ibmBreakdown.tsx index ae559ad64..427e840f8 100644 --- a/src/pages/views/details/ibmBreakdown/ibmBreakdown.tsx +++ b/src/pages/views/details/ibmBreakdown/ibmBreakdown.tsx @@ -1,4 +1,4 @@ -import { ProviderType } from 'api/providers'; +import { Providers, ProviderType } from 'api/providers'; import { getQuery, IbmQuery, parseQuery } from 'api/queries/ibmQuery'; import { getProvidersQuery } from 'api/queries/providersQuery'; import { breakdownDescKey, breakdownTitleKey, Query } from 'api/queries/query'; @@ -8,12 +8,13 @@ import { AxiosError } from 'axios'; import messages from 'locales/messages'; import BreakdownBase from 'pages/views/details/components/breakdown/breakdownBase'; import { getGroupById, getGroupByValue } from 'pages/views/utils/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { paths } from 'routes'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { ibmProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { CostOverview } from './costOverview'; @@ -25,6 +26,9 @@ interface IbmBreakdownStateProps { CostOverview?: React.ReactNode; detailsURL: string; HistoricalData?: React.ReactNode; + providers: Providers; + providersError: AxiosError; + providersFetchStatus: FetchStatus; query: Query; queryString: string; report: Report; @@ -69,11 +73,12 @@ const mapStateToProps = createMapStateToProps<IbmBreakdownOwnProps, IbmBreakdown const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(ibmProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.ibm, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.ibm, + ProviderType.all, providersQueryString ); @@ -85,7 +90,8 @@ const mapStateToProps = createMapStateToProps<IbmBreakdownOwnProps, IbmBreakdown groupBy, groupByValue, historicalDataComponent: <HistoricalData />, - providers, + providers: filterProviders(providers, ProviderType.ibm), + providersError, providersFetchStatus, providerType: ProviderType.ibm, query, diff --git a/src/pages/views/details/ibmDetails/detailsHeader.tsx b/src/pages/views/details/ibmDetails/detailsHeader.tsx index bb1ea3920..f3c2cb134 100644 --- a/src/pages/views/details/ibmDetails/detailsHeader.tsx +++ b/src/pages/views/details/ibmDetails/detailsHeader.tsx @@ -8,11 +8,12 @@ import { AxiosError } from 'axios'; import { Currency } from 'components/currency'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { ibmProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { ComputedIbmReportItemsParams, getIdKeyForGroupBy } from 'utils/computedReport/getComputedIbmReportItems'; import { getSinceDateRangeString } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; @@ -105,17 +106,18 @@ class DetailsHeaderBase extends React.Component<DetailsHeaderProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<DetailsHeaderOwnProps, DetailsHeaderStateProps>((state, props) => { const queryString = getQuery(baseQuery); - const providersQueryString = getProvidersQuery(ibmProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.ibm, providersQueryString); - const providersError = providersSelectors.selectProvidersError(state, ProviderType.ibm, providersQueryString); + + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.ibm, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.ibm), providersError, providersFetchStatus, queryString, diff --git a/src/pages/views/details/ibmDetails/ibmDetails.tsx b/src/pages/views/details/ibmDetails/ibmDetails.tsx index 873ffe47b..39797c98f 100644 --- a/src/pages/views/details/ibmDetails/ibmDetails.tsx +++ b/src/pages/views/details/ibmDetails/ibmDetails.tsx @@ -14,13 +14,14 @@ import NotAvailable from 'pages/state/notAvailable'; import { ExportModal } from 'pages/views/components/export/exportModal'; import { getGroupByTagKey } from 'pages/views/utils/groupBy'; import { hasCurrentMonthData } from 'pages/views/utils/providers'; +import { filterProviders } from 'pages/views/utils/providers'; import { addQueryFilter, removeQueryFilter } from 'pages/views/utils/query'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { ibmProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { uiActions } from 'store/ui'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedIbmReportItems'; @@ -33,6 +34,7 @@ import { styles } from './ibmDetails.styles'; interface IbmDetailsStateProps { providers: Providers; + providersError: AxiosError; providersFetchStatus: FetchStatus; query: IbmQuery; queryString: string; @@ -436,16 +438,18 @@ const mapStateToProps = createMapStateToProps<IbmDetailsOwnProps, IbmDetailsStat const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(ibmProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.ibm, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.ibm, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.ibm), + providersError, providersFetchStatus, query, queryString, From 480bdd46197415ff691eda18782b600ecec01b9d Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:21:50 -0500 Subject: [PATCH 25/29] Modified OCP details to use single source API request --- .../views/details/ocpBreakdown/ocpBreakdown.tsx | 11 ++++++----- .../views/details/ocpDetails/detailsHeader.tsx | 14 ++++++++------ src/pages/views/details/ocpDetails/ocpDetails.tsx | 12 ++++++------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/pages/views/details/ocpBreakdown/ocpBreakdown.tsx b/src/pages/views/details/ocpBreakdown/ocpBreakdown.tsx index e9a1bceff..7d44a476b 100644 --- a/src/pages/views/details/ocpBreakdown/ocpBreakdown.tsx +++ b/src/pages/views/details/ocpBreakdown/ocpBreakdown.tsx @@ -8,12 +8,13 @@ import { AxiosError } from 'axios'; import messages from 'locales/messages'; import BreakdownBase from 'pages/views/details/components/breakdown/breakdownBase'; import { getGroupById, getGroupByValue } from 'pages/views/utils/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { paths } from 'routes'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { ocpProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { CostOverview } from './costOverview'; @@ -69,11 +70,11 @@ const mapStateToProps = createMapStateToProps<OcpBreakdownOwnProps, OcpBreakdown const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(ocpProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.ocp, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.ocp, + ProviderType.all, providersQueryString ); @@ -85,7 +86,7 @@ const mapStateToProps = createMapStateToProps<OcpBreakdownOwnProps, OcpBreakdown groupBy, groupByValue, historicalDataComponent: <HistoricalData />, - providers, + providers: filterProviders(providers, ProviderType.ocp), providersFetchStatus, providerType: ProviderType.ocp, query, diff --git a/src/pages/views/details/ocpDetails/detailsHeader.tsx b/src/pages/views/details/ocpDetails/detailsHeader.tsx index 1b7387100..71cc1d4b0 100644 --- a/src/pages/views/details/ocpDetails/detailsHeader.tsx +++ b/src/pages/views/details/ocpDetails/detailsHeader.tsx @@ -9,11 +9,12 @@ import { Currency } from 'components/currency'; import { EmptyValueState } from 'components/state/emptyValueState/emptyValueState'; import messages from 'locales/messages'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; +import { filterProviders } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { ocpProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { ComputedOcpReportItemsParams, getIdKeyForGroupBy } from 'utils/computedReport/getComputedOcpReportItems'; import { getSinceDateRangeString } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; @@ -134,17 +135,18 @@ class DetailsHeaderBase extends React.Component<DetailsHeaderProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<DetailsHeaderOwnProps, DetailsHeaderStateProps>((state, props) => { const queryString = getQuery(baseQuery); - const providersQueryString = getProvidersQuery(ocpProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.ocp, providersQueryString); - const providersError = providersSelectors.selectProvidersError(state, ProviderType.ocp, providersQueryString); + + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.ocp, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.ocp), providersError, providersFetchStatus, queryString, diff --git a/src/pages/views/details/ocpDetails/ocpDetails.tsx b/src/pages/views/details/ocpDetails/ocpDetails.tsx index 6f0a947c3..3b6ad85cd 100644 --- a/src/pages/views/details/ocpDetails/ocpDetails.tsx +++ b/src/pages/views/details/ocpDetails/ocpDetails.tsx @@ -19,14 +19,14 @@ import { initHiddenColumns, } from 'pages/views/details/components/columnManagement/columnManagementModal'; import { getGroupByTagKey } from 'pages/views/utils/groupBy'; -import { hasCurrentMonthData } from 'pages/views/utils/providers'; +import { filterProviders, hasCurrentMonthData } from 'pages/views/utils/providers'; import { addQueryFilter, removeQueryFilter } from 'pages/views/utils/query'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { ocpProvidersQuery, providersSelectors } from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { uiActions } from 'store/ui'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedOcpReportItems'; @@ -499,16 +499,16 @@ const mapStateToProps = createMapStateToProps<OcpDetailsOwnProps, OcpDetailsStat const reportError = reportSelectors.selectReportError(state, reportPathsType, reportType, queryString); const reportFetchStatus = reportSelectors.selectReportFetchStatus(state, reportPathsType, reportType, queryString); - const providersQueryString = getProvidersQuery(ocpProvidersQuery); - const providers = providersSelectors.selectProviders(state, ProviderType.ocp, providersQueryString); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, - ProviderType.ocp, + ProviderType.all, providersQueryString ); return { - providers, + providers: filterProviders(providers, ProviderType.ocp), providersFetchStatus, query, queryString, From 8e838277d2254694a24281b701b1047e5cfc98c9 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:22:22 -0500 Subject: [PATCH 26/29] Modified Explorer to use single source API request --- src/pages/views/explorer/explorer.tsx | 147 +++++-------------- src/pages/views/explorer/explorerHeader.tsx | 153 +++++--------------- 2 files changed, 73 insertions(+), 227 deletions(-) diff --git a/src/pages/views/explorer/explorer.tsx b/src/pages/views/explorer/explorer.tsx index eb9592854..ab9141e9c 100644 --- a/src/pages/views/explorer/explorer.tsx +++ b/src/pages/views/explorer/explorer.tsx @@ -14,24 +14,17 @@ import NoProviders from 'pages/state/noProviders'; import NotAvailable from 'pages/state/notAvailable'; import { ExportModal } from 'pages/views/components/export/exportModal'; import { getGroupByOrgValue, getGroupByTagKey } from 'pages/views/utils/groupBy'; -import { hasData } from 'pages/views/utils/providers'; +import { filterProviders, hasData } from 'pages/views/utils/providers'; import { addQueryFilter, removeQueryFilter } from 'pages/views/utils/query'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { - awsProvidersQuery, - azureProvidersQuery, - gcpProvidersQuery, - ibmProvidersQuery, - ocpProvidersQuery, - providersSelectors, -} from 'store/providers'; +import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { uiActions } from 'store/ui'; -import { ibmUserAccessQuery, userAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedExplorerReportItems'; import { ComputedReportItem, getUnsortedComputedReportItems } from 'utils/computedReport/getComputedReportItems'; import { isAwsAvailable, isAzureAvailable, isGcpAvailable, isIbmAvailable, isOcpAvailable } from 'utils/userAccess'; @@ -58,26 +51,16 @@ import { interface ExplorerStateProps { awsProviders: Providers; - awsProvidersFetchStatus: FetchStatus; - awsProvidersQueryString: string; azureProviders: Providers; - azureProvidersFetchStatus: FetchStatus; - azureProvidersQueryString: string; dateRange: DateRangeType; gcpProviders: Providers; - gcpProvidersFetchStatus: FetchStatus; - gcpProvidersQueryString: string; ibmProviders: Providers; - ibmProvidersFetchStatus: FetchStatus; - ibmProvidersQueryString: string; - ibmUserAccess: UserAccess; - ibmUserAccessError: AxiosError; - ibmUserAccessFetchStatus: FetchStatus; - ibmUserAccessQueryString: string; ocpProviders: Providers; - ocpProvidersFetchStatus: FetchStatus; - ocpProvidersQueryString: string; perspective: PerspectiveType; + providers: Providers; + providersError: AxiosError; + providersFetchStatus: FetchStatus; + providersQueryString: string; query: Query; queryString: string; report: Report; @@ -411,8 +394,8 @@ class Explorer extends React.Component<ExplorerProps> { }; private isIbmAvailable = () => { - const { ibmProviders, ibmUserAccess } = this.props; - return isIbmAvailable(ibmUserAccess, ibmProviders); + const { ibmProviders, userAccess } = this.props; + return isIbmAvailable(userAccess, ibmProviders); }; private isOcpAvailable = () => { @@ -439,17 +422,12 @@ class Explorer extends React.Component<ExplorerProps> { public render() { const { awsProviders, - awsProvidersFetchStatus, azureProviders, - azureProvidersFetchStatus, gcpProviders, - gcpProvidersFetchStatus, ibmProviders, - ibmProvidersFetchStatus, - ibmUserAccessFetchStatus, intl, ocpProviders, - ocpProvidersFetchStatus, + providersFetchStatus, perspective, userAccessFetchStatus, query, @@ -459,21 +437,15 @@ class Explorer extends React.Component<ExplorerProps> { } = this.props; // Note: No need to test OCP on cloud here, since that requires at least one provider - const noAwsProviders = !this.isAwsAvailable() && awsProvidersFetchStatus === FetchStatus.complete; - const noAzureProviders = !this.isAzureAvailable() && azureProvidersFetchStatus === FetchStatus.complete; - const noGcpProviders = !this.isGcpAvailable() && gcpProvidersFetchStatus === FetchStatus.complete; - const noIbmProviders = !this.isIbmAvailable() && ibmProvidersFetchStatus === FetchStatus.complete; - const noOcpProviders = !this.isOcpAvailable() && ocpProvidersFetchStatus === FetchStatus.complete; + const noAwsProviders = !this.isAwsAvailable() && providersFetchStatus === FetchStatus.complete; + const noAzureProviders = !this.isAzureAvailable() && providersFetchStatus === FetchStatus.complete; + const noGcpProviders = !this.isGcpAvailable() && providersFetchStatus === FetchStatus.complete; + const noIbmProviders = !this.isIbmAvailable() && providersFetchStatus === FetchStatus.complete; + const noOcpProviders = !this.isOcpAvailable() && providersFetchStatus === FetchStatus.complete; const noProviders = noAwsProviders && noAzureProviders && noGcpProviders && noIbmProviders && noOcpProviders; const isLoading = - awsProvidersFetchStatus === FetchStatus.inProgress || - azureProvidersFetchStatus === FetchStatus.inProgress || - gcpProvidersFetchStatus === FetchStatus.inProgress || - ibmProvidersFetchStatus === FetchStatus.inProgress || - ocpProvidersFetchStatus === FetchStatus.inProgress || - userAccessFetchStatus === FetchStatus.inProgress || - ibmUserAccessFetchStatus === FetchStatus.inProgress; + providersFetchStatus === FetchStatus.inProgress || userAccessFetchStatus === FetchStatus.inProgress; const groupById = getIdKeyForGroupBy(query.group_by); const groupByTagKey = getGroupByTagKey(query); @@ -542,6 +514,21 @@ class Explorer extends React.Component<ExplorerProps> { // eslint-disable-next-line @typescript-eslint/no-unused-vars const mapStateToProps = createMapStateToProps<ExplorerOwnProps, ExplorerStateProps>((state, props) => { + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); + const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( + state, + ProviderType.all, + providersQueryString + ); + + const awsProviders = filterProviders(providers, ProviderType.aws); + const azureProviders = filterProviders(providers, ProviderType.azure); + const gcpProviders = filterProviders(providers, ProviderType.gcp); + const ibmProviders = filterProviders(providers, ProviderType.ibm); + const ocpProviders = filterProviders(providers, ProviderType.ocp); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); @@ -551,60 +538,6 @@ const mapStateToProps = createMapStateToProps<ExplorerOwnProps, ExplorerStatePro userAccessQueryString ); - const awsProvidersQueryString = getProvidersQuery(awsProvidersQuery); - const awsProviders = providersSelectors.selectProviders(state, ProviderType.aws, awsProvidersQueryString); - const awsProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.aws, - awsProvidersQueryString - ); - - const azureProvidersQueryString = getProvidersQuery(azureProvidersQuery); - const azureProviders = providersSelectors.selectProviders(state, ProviderType.azure, azureProvidersQueryString); - const azureProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.azure, - azureProvidersQueryString - ); - - const gcpProvidersQueryString = getProvidersQuery(gcpProvidersQuery); - const gcpProviders = providersSelectors.selectProviders(state, ProviderType.gcp, gcpProvidersQueryString); - const gcpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.gcp, - gcpProvidersQueryString - ); - - const ibmProvidersQueryString = getProvidersQuery(ibmProvidersQuery); - const ibmProviders = providersSelectors.selectProviders(state, ProviderType.ibm, ibmProvidersQueryString); - const ibmProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ibm, - ibmProvidersQueryString - ); - - const ocpProvidersQueryString = getProvidersQuery(ocpProvidersQuery); - const ocpProviders = providersSelectors.selectProviders(state, ProviderType.ocp, ocpProvidersQueryString); - const ocpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ocp, - ocpProvidersQueryString - ); - - // Todo: temporarily request IBM separately with beta flag. - const ibmUserAccessQueryString = getUserAccessQuery(ibmUserAccessQuery); - const ibmUserAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.ibm, ibmUserAccessQueryString); - const ibmUserAccessError = userAccessSelectors.selectUserAccessError( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - const ibmUserAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - // Cost Report const queryFromRoute = parseQuery<Query>(location.search); const dateRange = getDateRangeDefault(queryFromRoute); @@ -655,26 +588,16 @@ const mapStateToProps = createMapStateToProps<ExplorerOwnProps, ExplorerStatePro return { awsProviders, - awsProvidersFetchStatus, - awsProvidersQueryString, azureProviders, - azureProvidersFetchStatus, - azureProvidersQueryString, dateRange, gcpProviders, - gcpProvidersFetchStatus, - gcpProvidersQueryString, ibmProviders, - ibmProvidersFetchStatus, - ibmProvidersQueryString, - ibmUserAccess, - ibmUserAccessError, - ibmUserAccessFetchStatus, - ibmUserAccessQueryString, ocpProviders, - ocpProvidersFetchStatus, - ocpProvidersQueryString, perspective, + providers, + providersError, + providersFetchStatus, + providersQueryString, query, queryString, report, diff --git a/src/pages/views/explorer/explorerHeader.tsx b/src/pages/views/explorer/explorerHeader.tsx index 5c99863c9..cbf114ee0 100644 --- a/src/pages/views/explorer/explorerHeader.tsx +++ b/src/pages/views/explorer/explorerHeader.tsx @@ -10,21 +10,14 @@ import messages from 'locales/messages'; import { CostType } from 'pages/views/components/costType'; import { GroupBy } from 'pages/views/components/groupBy/groupBy'; import { Perspective } from 'pages/views/components/perspective/perspective'; -import { hasCloudProvider } from 'pages/views/utils/providers'; +import { filterProviders, hasCloudProvider } from 'pages/views/utils/providers'; import React from 'react'; import { injectIntl, WrappedComponentProps } from 'react-intl'; import { connect } from 'react-redux'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; -import { - awsProvidersQuery, - azureProvidersQuery, - gcpProvidersQuery, - ibmProvidersQuery, - ocpProvidersQuery, - providersSelectors, -} from 'store/providers'; -import { ibmUserAccessQuery, userAccessQuery, userAccessSelectors } from 'store/userAccess'; +import { providersQuery, providersSelectors } from 'store/providers'; +import { userAccessQuery, userAccessSelectors } from 'store/userAccess'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedExplorerReportItems'; import { getLast60DaysDate } from 'utils/dateRange'; import { isBetaFeature } from 'utils/feature'; @@ -74,25 +67,15 @@ interface ExplorerHeaderOwnProps { } interface ExplorerHeaderStateProps { - awsProviders: Providers; - awsProvidersFetchStatus: FetchStatus; - awsProvidersQueryString: string; - azureProviders: Providers; - azureProvidersFetchStatus: FetchStatus; - azureProvidersQueryString: string; - gcpProviders: Providers; - gcpProvidersFetchStatus: FetchStatus; - gcpProvidersQueryString: string; - ibmProviders: Providers; - ibmProvidersFetchStatus: FetchStatus; - ibmProvidersQueryString: string; - ibmUserAccess: UserAccess; - ibmUserAccessError: AxiosError; - ibmUserAccessFetchStatus: FetchStatus; - ibmUserAccessQueryString: string; - ocpProviders: Providers; - ocpProvidersFetchStatus: FetchStatus; - ocpProvidersQueryString: string; + awsProviders?: Providers; + azureProviders?: Providers; + gcpProviders?: Providers; + ibmProviders?: Providers; + ocpProviders?: Providers; + providers: Providers; + providersError: AxiosError; + providersFetchStatus: FetchStatus; + providersQueryString: string; query: Query; queryString: string; userAccess: UserAccess; @@ -251,8 +234,8 @@ class ExplorerHeaderBase extends React.Component<ExplorerHeaderProps> { }; private isIbmAvailable = () => { - const { ibmProviders, ibmUserAccess } = this.props; - return isIbmAvailable(ibmUserAccess, ibmProviders); + const { ibmProviders, userAccess } = this.props; + return isIbmAvailable(userAccess, ibmProviders); }; private isIbmCloudAvailable = () => { @@ -276,26 +259,22 @@ class ExplorerHeaderBase extends React.Component<ExplorerHeaderProps> { public render() { const { - awsProvidersFetchStatus, - azureProvidersFetchStatus, - gcpProvidersFetchStatus, - ibmProvidersFetchStatus, - ocpProvidersFetchStatus, groupBy, intl, onFilterAdded, onFilterRemoved, onGroupBySelected, perspective, + providersFetchStatus, query, } = this.props; // Note: No need to test OCP on cloud here, since that requires at least one provider - const noAwsProviders = !this.isAwsAvailable() && awsProvidersFetchStatus === FetchStatus.complete; - const noAzureProviders = !this.isAzureAvailable() && azureProvidersFetchStatus === FetchStatus.complete; - const noGcpProviders = !this.isGcpAvailable() && gcpProvidersFetchStatus === FetchStatus.complete; - const noIbmProviders = !this.isIbmAvailable() && ibmProvidersFetchStatus === FetchStatus.complete; - const noOcpProviders = !this.isOcpAvailable() && ocpProvidersFetchStatus === FetchStatus.complete; + const noAwsProviders = !this.isAwsAvailable() && providersFetchStatus === FetchStatus.complete; + const noAzureProviders = !this.isAzureAvailable() && providersFetchStatus === FetchStatus.complete; + const noGcpProviders = !this.isGcpAvailable() && providersFetchStatus === FetchStatus.complete; + const noIbmProviders = !this.isIbmAvailable() && providersFetchStatus === FetchStatus.complete; + const noOcpProviders = !this.isOcpAvailable() && providersFetchStatus === FetchStatus.complete; const noProviders = noAwsProviders && noAzureProviders && noGcpProviders && noIbmProviders && noOcpProviders; const groupByOptions = getGroupByOptions(perspective); @@ -360,6 +339,15 @@ const mapStateToProps = createMapStateToProps<ExplorerHeaderOwnProps, ExplorerHe const dateRange = getDateRangeDefault(queryFromRoute); const { end_date, start_date } = getDateRange(getDateRangeDefault(queryFromRoute)); + const providersQueryString = getProvidersQuery(providersQuery); + const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); + const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( + state, + ProviderType.all, + providersQueryString + ); + const userAccessQueryString = getUserAccessQuery(userAccessQuery); const userAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.all, userAccessQueryString); const userAccessError = userAccessSelectors.selectUserAccessError(state, UserAccessType.all, userAccessQueryString); @@ -395,81 +383,16 @@ const mapStateToProps = createMapStateToProps<ExplorerHeaderOwnProps, ExplorerHe dateRange: undefined, }); - const awsProvidersQueryString = getProvidersQuery(awsProvidersQuery); - const awsProviders = providersSelectors.selectProviders(state, ProviderType.aws, awsProvidersQueryString); - const awsProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.aws, - awsProvidersQueryString - ); - - const azureProvidersQueryString = getProvidersQuery(azureProvidersQuery); - const azureProviders = providersSelectors.selectProviders(state, ProviderType.azure, azureProvidersQueryString); - const azureProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.azure, - azureProvidersQueryString - ); - - const gcpProvidersQueryString = getProvidersQuery(gcpProvidersQuery); - const gcpProviders = providersSelectors.selectProviders(state, ProviderType.gcp, gcpProvidersQueryString); - const gcpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.gcp, - gcpProvidersQueryString - ); - - const ibmProvidersQueryString = getProvidersQuery(ibmProvidersQuery); - const ibmProviders = providersSelectors.selectProviders(state, ProviderType.ibm, ibmProvidersQueryString); - const ibmProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ibm, - ibmProvidersQueryString - ); - - const ocpProvidersQueryString = getProvidersQuery(ocpProvidersQuery); - const ocpProviders = providersSelectors.selectProviders(state, ProviderType.ocp, ocpProvidersQueryString); - const ocpProvidersFetchStatus = providersSelectors.selectProvidersFetchStatus( - state, - ProviderType.ocp, - ocpProvidersQueryString - ); - - // Todo: temporarily request IBM separately with beta flag. - const ibmUserAccessQueryString = getUserAccessQuery(ibmUserAccessQuery); - const ibmUserAccess = userAccessSelectors.selectUserAccess(state, UserAccessType.ibm, ibmUserAccessQueryString); - const ibmUserAccessError = userAccessSelectors.selectUserAccessError( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - const ibmUserAccessFetchStatus = userAccessSelectors.selectUserAccessFetchStatus( - state, - UserAccessType.ibm, - ibmUserAccessQueryString - ); - return { - awsProviders, - awsProvidersFetchStatus, - awsProvidersQueryString, - azureProviders, - azureProvidersFetchStatus, - azureProvidersQueryString, - gcpProviders, - gcpProvidersFetchStatus, - gcpProvidersQueryString, - ibmProviders, - ibmProvidersFetchStatus, - ibmProvidersQueryString, - ibmUserAccess, - ibmUserAccessError, - ibmUserAccessFetchStatus, - ibmUserAccessQueryString, - ocpProviders, - ocpProvidersFetchStatus, - ocpProvidersQueryString, - perspective, + awsProviders: filterProviders(providers, ProviderType.aws), + azureProviders: filterProviders(providers, ProviderType.azure), + gcpProviders: filterProviders(providers, ProviderType.gcp), + ibmProviders: filterProviders(providers, ProviderType.ibm), + ocpProviders: filterProviders(providers, ProviderType.ocp), + providers, + providersError, + providersFetchStatus, + providersQueryString, query, queryString, userAccess, From 245b3b17850b753d0564d310685f1d0f293d155a Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:22:47 -0500 Subject: [PATCH 27/29] Modified Overview to use single source API request --- src/pages/views/overview/overview.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/views/overview/overview.tsx b/src/pages/views/overview/overview.tsx index c11b2d0b4..36f754595 100644 --- a/src/pages/views/overview/overview.tsx +++ b/src/pages/views/overview/overview.tsx @@ -113,8 +113,8 @@ interface OverviewStateProps { ibmProviders?: Providers; ocpProviders?: Providers; providers: Providers; + providersError: AxiosError; providersFetchStatus: FetchStatus; - providersQueryString: string; perspective?: string; query: OverviewQuery; queryString: string; @@ -703,6 +703,7 @@ const mapStateToProps = createMapStateToProps<OverviewOwnProps, OverviewStatePro const providersQueryString = getProvidersQuery(providersQuery); const providers = providersSelectors.selectProviders(state, ProviderType.all, providersQueryString); + const providersError = providersSelectors.selectProvidersError(state, ProviderType.all, providersQueryString); const providersFetchStatus = providersSelectors.selectProvidersFetchStatus( state, ProviderType.all, @@ -725,8 +726,8 @@ const mapStateToProps = createMapStateToProps<OverviewOwnProps, OverviewStatePro ibmProviders: filterProviders(providers, ProviderType.ibm), ocpProviders: filterProviders(providers, ProviderType.ocp), providers, + providersError, providersFetchStatus, - providersQueryString, perspective, query, queryString, From 9ca274f0c7dff251f2aba3399cbdc5d294cd8ce5 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Mon, 17 Jan 2022 15:24:52 -0500 Subject: [PATCH 28/29] Modified filter providers util to correct source counts https://issues.redhat.com/browse/COST-2202 --- .../views/details/components/breakdown/breakdownBase.tsx | 1 + src/pages/views/utils/providers.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/pages/views/details/components/breakdown/breakdownBase.tsx b/src/pages/views/details/components/breakdown/breakdownBase.tsx index 57295e6fc..7543bc49b 100644 --- a/src/pages/views/details/components/breakdown/breakdownBase.tsx +++ b/src/pages/views/details/components/breakdown/breakdownBase.tsx @@ -42,6 +42,7 @@ interface BreakdownStateProps { groupBy?: string; historicalDataComponent?: React.ReactNode; providers?: Providers; + providersError?: AxiosError; providersFetchStatus?: FetchStatus; providerType?: ProviderType; query: Query; diff --git a/src/pages/views/utils/providers.ts b/src/pages/views/utils/providers.ts index ac23d7d1f..e3d31ece6 100644 --- a/src/pages/views/utils/providers.ts +++ b/src/pages/views/utils/providers.ts @@ -29,8 +29,14 @@ export const filterProviders = (providers: Providers, sourceType: ProviderType) } const data = providers.data.filter(provider => provider.source_type.toLowerCase() === sourceType); + const meta = { + ...providers.meta, + count: data.length, + }; + return { ...providers, + meta, data, } as Providers; }; From e303c6fe689425740c970efda88be9da80a342a1 Mon Sep 17 00:00:00 2001 From: Dan Labrecque <dlabrecq@redhat.com> Date: Tue, 18 Jan 2022 09:02:04 -0500 Subject: [PATCH 29/29] Added sources API comment to ref COST-2202 --- src/pages/views/utils/providers.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/views/utils/providers.ts b/src/pages/views/utils/providers.ts index e3d31ece6..ec727f1cc 100644 --- a/src/pages/views/utils/providers.ts +++ b/src/pages/views/utils/providers.ts @@ -23,6 +23,8 @@ const _getOcpProvider = (ocpProviders: Providers, uuid?: string) => { }; // Returns new Provider matching the given provider type +// +// See https://issues.redhat.com/browse/COST-2202 export const filterProviders = (providers: Providers, sourceType: ProviderType) => { if (!providers) { return providers;