diff --git a/.eslintrc.json b/.eslintrc.json index c1a666124..aac000844 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -88,6 +88,9 @@ "no-eval": "error", "no-new-wrappers": "error", "no-prototype-builtins": "off", + "no-restricted-imports": ["error", { + "patterns": ["../*/**"] + }], "no-shadow": "error", "no-throw-literal": "error", "no-trailing-spaces": "off", diff --git a/jest.config.js b/jest.config.js index b74bf9a42..03e16df0f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,9 +3,10 @@ module.exports = { clearMocks: true, timers: 'fake', transform: { - '^.+\\.(ts|tsx)$': '/test/transformTS.js', + '^.+\\.[jt]sx?$': '/test/transformTS.js', '^.+\\.(jpg)$': '/test/transformFile.js', }, + transformIgnorePatterns: ['node_modules/(?!@patternfly/react-icons/dist/esm)'], setupFiles: ['./test/test.env.ts'], testRegex: '\\.test\\.(jsx?|tsx?)$', moduleFileExtensions: ['ts', 'tsx', 'js'], @@ -13,7 +14,7 @@ module.exports = { moduleNameMapper: { '\\.(css|less|sass|scss)$': '/test/styleMock.js', }, + roots: ['/src'], snapshotSerializers: ['enzyme-to-json/serializer'], - testPathIgnorePatterns: ['/archive/'], testURL: 'http://localhost/', }; diff --git a/koku-ui-manifest b/koku-ui-manifest index a309d9ffe..a53a1b071 100644 --- a/koku-ui-manifest +++ b/koku-ui-manifest @@ -83,17 +83,25 @@ mgmt_services/cost-mgmt:koku-ui/@formatjs/cli:4.2.12.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/ecma402-abstract:1.7.1.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/ecma402-abstract:1.8.0.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/ecma402-abstract:1.9.6.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/ecma402-abstract:1.9.7.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/fast-memoize:1.1.1.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/fast-memoize:1.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-messageformat-parser:2.0.1.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-messageformat-parser:2.0.10.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-messageformat-parser:2.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-messageformat-parser:2.0.9.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-skeleton-parser:1.2.10.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-skeleton-parser:1.2.11.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-skeleton-parser:1.2.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/icu-skeleton-parser:1.2.3.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/intl-displaynames:5.1.0.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/intl-displaynames:5.2.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/intl-listformat:6.1.0.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/intl-listformat:6.3.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/intl-localematcher:0.2.19.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/intl-localematcher:0.2.20.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/intl:1.10.8.yarnlock +mgmt_services/cost-mgmt:koku-ui/@formatjs/intl:1.14.0.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/ts-transformer:3.3.12.yarnlock mgmt_services/cost-mgmt:koku-ui/@formatjs/ts-transformer:3.4.7.yarnlock mgmt_services/cost-mgmt:koku-ui/@fortawesome/fontawesome-common-types:0.2.35.yarnlock @@ -127,6 +135,7 @@ mgmt_services/cost-mgmt:koku-ui/@patternfly/react-tokens:4.12.9.yarnlock mgmt_services/cost-mgmt:koku-ui/@popperjs/core:2.9.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@redhat-cloud-services/frontend-components-config-utilities:1.4.6.yarnlock mgmt_services/cost-mgmt:koku-ui/@redhat-cloud-services/frontend-components-notifications:3.2.2.yarnlock +mgmt_services/cost-mgmt:koku-ui/@redhat-cloud-services/frontend-components-translations:3.2.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@redhat-cloud-services/frontend-components-utilities:3.2.3.yarnlock mgmt_services/cost-mgmt:koku-ui/@redhat-cloud-services/frontend-components-utilities:3.2.3.yarnlock mgmt_services/cost-mgmt:koku-ui/@redhat-cloud-services/frontend-components-utilities:3.2.3.yarnlock @@ -210,6 +219,7 @@ mgmt_services/cost-mgmt:koku-ui/@types/react-transition-group:4.4.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@types/react:17.0.14.yarnlock mgmt_services/cost-mgmt:koku-ui/@types/react:17.0.14.yarnlock mgmt_services/cost-mgmt:koku-ui/@types/react:17.0.14.yarnlock +mgmt_services/cost-mgmt:koku-ui/@types/react:17.0.18.yarnlock mgmt_services/cost-mgmt:koku-ui/@types/react:17.0.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@types/scheduler:0.16.2.yarnlock mgmt_services/cost-mgmt:koku-ui/@types/source-list-map:0.1.2.yarnlock @@ -444,6 +454,7 @@ mgmt_services/cost-mgmt:koku-ui/commander:8.0.0.yarnlock mgmt_services/cost-mgmt:koku-ui/commander:2.20.3.yarnlock mgmt_services/cost-mgmt:koku-ui/commander:2.20.3.yarnlock mgmt_services/cost-mgmt:koku-ui/commander:4.1.1.yarnlock +mgmt_services/cost-mgmt:koku-ui/commander:8.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/comment-parser:1.1.6-beta.0.yarnlock mgmt_services/cost-mgmt:koku-ui/component-emitter:1.3.0.yarnlock mgmt_services/cost-mgmt:koku-ui/compressible:2.0.18.yarnlock @@ -844,6 +855,7 @@ mgmt_services/cost-mgmt:koku-ui/internal-ip:4.3.0.yarnlock mgmt_services/cost-mgmt:koku-ui/internal-slot:1.0.3.yarnlock mgmt_services/cost-mgmt:koku-ui/interpret:2.2.0.yarnlock mgmt_services/cost-mgmt:koku-ui/intl-messageformat:9.6.14.yarnlock +mgmt_services/cost-mgmt:koku-ui/intl-messageformat:9.9.0.yarnlock mgmt_services/cost-mgmt:koku-ui/invariant:2.2.4.yarnlock mgmt_services/cost-mgmt:koku-ui/ip-regex:2.1.0.yarnlock mgmt_services/cost-mgmt:koku-ui/ip:1.1.5.yarnlock @@ -1282,6 +1294,7 @@ mgmt_services/cost-mgmt:koku-ui/react-fast-compare:2.0.4.yarnlock mgmt_services/cost-mgmt:koku-ui/react-i18next:11.11.3.yarnlock mgmt_services/cost-mgmt:koku-ui/react-i18next:11.8.15.yarnlock mgmt_services/cost-mgmt:koku-ui/react-intl:5.17.7.yarnlock +mgmt_services/cost-mgmt:koku-ui/react-intl:5.20.9.yarnlock mgmt_services/cost-mgmt:koku-ui/react-is:16.13.1.yarnlock mgmt_services/cost-mgmt:koku-ui/react-is:16.13.1.yarnlock mgmt_services/cost-mgmt:koku-ui/react-is:16.13.1.yarnlock diff --git a/package.json b/package.json index dbc7c6081..23df32245 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "start": "node scripts/start-dev-server.js", "start:dev": "NODE_OPTIONS=--max-old-space-size=8192 webpack serve -c ./webpack.config.js", "stats": "yarn build:client --profile --json > stats.json", - "test": "jest", + "test": "jest --clearCache && jest", "manifest:update": "node scripts/createManifest", "codemods:test": "yarn pf-codemods ./src", "container:test": "docker stop -t 0 koku-ui-test >/dev/null; docker build -t koku-ui-test . && docker run -i --rm -p 8080:8080 --name koku-ui-test koku-ui-test", @@ -41,6 +41,7 @@ "@patternfly/react-tokens": "^4.12.9", "@redhat-cloud-services/frontend-components": "^3.3.8", "@redhat-cloud-services/frontend-components-notifications": "^3.2.2", + "@redhat-cloud-services/frontend-components-translations": "^3.2.2", "@redhat-cloud-services/frontend-components-utilities": "^3.2.3", "@redhat-cloud-services/rbac-client": "^1.0.100", "@types/date-fns": "2.6.0", @@ -67,6 +68,7 @@ "react-bootstrap": "1.5.0", "react-dom": "17.0.1", "react-i18next": "11.8.15", + "react-intl": "5.17.7", "react-redux": "7.2.2", "react-router-dom": "5.2.0", "redux": "4.0.5", @@ -88,6 +90,7 @@ "@xstate/test": "0.4.2", "@yarnpkg/lockfile": "1.1.0", "aphrodite": "2.4.0", + "commander": "^8.1.0", "copy-webpack-plugin": "7.0.0", "css-loader": "6.2.0", "enzyme": "3.11.0", @@ -116,7 +119,6 @@ "nodesi": "^1.16.0", "null-loader": "4.0.1", "prettier": "2.3.2", - "react-intl": "5.17.7", "rimraf": "^3.0.2", "sass": "^1.32.7", "sass-loader": "^11.0.1", diff --git a/scripts/rebase-branch.sh b/scripts/rebase-branch.sh deleted file mode 100755 index 531d87d17..000000000 --- a/scripts/rebase-branch.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh - -default() -{ - PATH=/usr/bin:/usr/sbin:${PATH} - export PATH - - SCRIPT=`basename $0` - SCRIPT_DIR=`dirname $0` - SCRIPT_DIR=`cd $SCRIPT_DIR; pwd` - - MAIN_BRANCH="master" - CI_STABLE_BRANCH="ci-stable" - STAGE_STABLE_BRANCH="stage-stable" - REACT_INTL_BRANCH="react-intl_changeover" - - KOKU_UI_REPO="git@github.com:project-koku/koku-ui.git" - - TMP_DIR="/tmp/$SCRIPT.$$" - KOKU_UI_DIR="$TMP_DIR/koku-ui" -} - -usage() -{ -cat <<- EEOOFF - - This script will rebase the selected branch with $MAIN_BRANCH, then push changes to origin. - - FYI, there are no ci-beta and stage-beta branches -- we push to https://github.com/RedHatInsights/cost-management-build via Travis builds - - Note: The QA environment is no longer supported. - - sh [-x] $SCRIPT [-h] - - - OPTIONS: - h Display this message - c CI stable - s Stage stable - r React Intl - -EEOOFF -} - -# main() -{ - default - - while getopts hcqsr c; do - case $c in - c) BRANCH=$CI_STABLE_BRANCH;; - s) BRANCH=$STAGE_STABLE_BRANCH;; - r) BRANCH=$REACT_INTL_BRANCH;; - h) usage; exit 0;; - \?) usage; exit 1;; - esac - done - - if [ -z "$BRANCH" ]; then - usage - exit 1 - fi - - mkdir $TMP_DIR - cd $TMP_DIR - - git clone $KOKU_UI_REPO - cd $KOKU_UI_DIR - - git checkout $BRANCH - git rebase $MAIN_BRANCH - - if [ "$?" -eq 0 ]; then - git push -u origin $BRANCH - else - echo "Did not push to origin. No changes or check for conflicts" - fi - - rm -rf $TMP_DIR -} diff --git a/scripts/release-branch.sh b/scripts/release-branch.sh new file mode 100755 index 000000000..86b8c7d1f --- /dev/null +++ b/scripts/release-branch.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +default() +{ + PATH=/usr/bin:/usr/sbin:${PATH} + export PATH + + SCRIPT=`basename $0` + SCRIPT_DIR=`dirname $0` + SCRIPT_DIR=`cd $SCRIPT_DIR; pwd` + + MAIN_BRANCH="master" + PROD_BETA_BRANCH="prod-beta" + PROD_STABLE_BRANCH="prod-stable" + STAGE_STABLE_BRANCH="stage-stable" + + KOKU_UI_REPO="git@github.com:project-koku/koku-ui.git" + + TMP_DIR="/tmp/$SCRIPT.$$" + KOKU_UI_DIR="$TMP_DIR/koku-ui" +} + +usage() +{ +cat <<- EEOOFF + + This script will release the selected branch by merging the following branches + + stage-stage is merged from stage-beta + prod-beta is merged from stage-stable + prod-stable is merged from prod-beta + + sh [-x] $SCRIPT [-h] - + + OPTIONS: + h Display this message + b Prod beta + p Prod stable + s Stage stable + +EEOOFF +} + +clone() +{ + mkdir $TMP_DIR + cd $TMP_DIR + + git clone $KOKU_UI_REPO +} + + +merge() +{ + cd $KOKU_UI_DIR + + git checkout $BRANCH + + git fetch origin $REMOTE_BRANCH + git merge origin/$REMOTE_BRANCH --commit --no-edit +} + +push() +{ + read -p "You are pushing to the $BRANCH branch. Continue?" YN + + case $YN in + [Yy]* ) git push -u origin $BRANCH;; + [Nn]* ) exit 0;; + * ) echo "Please answer yes or no."; push;; + esac +} + +# main() +{ + default + + while getopts hbps c; do + case $c in + b) BRANCH=$PROD_BETA_BRANCH + REMOTE_BRANCH=$STAGE_STABLE_BRANCH;; + p) BRANCH=$PROD_STABLE_BRANCH + REMOTE_BRANCH=$PROD_BETA_BRANCH;; + s) BRANCH=$STAGE_STABLE_BRANCH + REMOTE_BRANCH=$MAIN_BRANCH;; + h) usage; exit 0;; + \?) usage; exit 1;; + esac + done + + if [ -z "$BRANCH" ]; then + usage + exit 1 + fi + + echo "\nMerging $BRANCH from $REMOTE_BRANCH\n" + + clone + merge + + if [ "$?" -eq 0 ]; then + push + else + echo "Cannot not push. No changes or check for conflicts" + fi + + rm -rf $TMP_DIR +} diff --git a/src/api/providers.ts b/src/api/providers.ts index c62b69ab7..143e4646f 100644 --- a/src/api/providers.ts +++ b/src/api/providers.ts @@ -30,6 +30,11 @@ export interface ProviderCostModel { uuid: string; } +export interface ProviderInfrastructure { + type?: string; + uuid?: string; +} + export interface Provider { active?: boolean; authentication?: ProviderAuthentication; @@ -40,6 +45,7 @@ export interface Provider { current_month_data?: boolean; customer?: ProviderCustomer; has_data?: boolean; + infrastructure?: ProviderInfrastructure; name?: string; previous_month_data?: boolean; type?: string; diff --git a/src/components/state/emptyFilterState/emptyFilterState.tsx b/src/components/state/emptyFilterState/emptyFilterState.tsx index 3ccec98ce..0247c1e67 100644 --- a/src/components/state/emptyFilterState/emptyFilterState.tsx +++ b/src/components/state/emptyFilterState/emptyFilterState.tsx @@ -1,5 +1,5 @@ import { EmptyState, EmptyStateBody, EmptyStateIcon, Title, TitleSizes } from '@patternfly/react-core'; -import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon'; +import { SearchIcon } from '@patternfly/react-icons/dist/esm/icons/search-icon'; import { OcpCloudQuery, parseQuery } from 'api/queries/ocpCloudQuery'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; diff --git a/src/components/state/emptyValueState/emptyValueState.tsx b/src/components/state/emptyValueState/emptyValueState.tsx index b6f1e42ca..b1d870a86 100644 --- a/src/components/state/emptyValueState/emptyValueState.tsx +++ b/src/components/state/emptyValueState/emptyValueState.tsx @@ -1,6 +1,6 @@ import './emptyValueState.scss'; -import { MinusIcon } from '@patternfly/react-icons/dist/js/icons/minus-icon'; +import { MinusIcon } from '@patternfly/react-icons/dist/esm/icons/minus-icon'; import React from 'react'; export const EmptyValueState: React.SFC = () => { diff --git a/src/components/state/errorState/errorState.tsx b/src/components/state/errorState/errorState.tsx index dfee078c6..292af593f 100644 --- a/src/components/state/errorState/errorState.tsx +++ b/src/components/state/errorState/errorState.tsx @@ -1,6 +1,6 @@ import { EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStateVariant, Title } from '@patternfly/react-core'; -import { ErrorCircleOIcon } from '@patternfly/react-icons/dist/js/icons/error-circle-o-icon'; -import { LockIcon } from '@patternfly/react-icons/dist/js/icons/lock-icon'; +import { ErrorCircleOIcon } from '@patternfly/react-icons/dist/esm/icons/error-circle-o-icon'; +import { LockIcon } from '@patternfly/react-icons/dist/esm/icons/lock-icon'; import { AxiosError } from 'axios'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; diff --git a/src/locales/en.json b/src/locales/en.json index 01aa8629d..42a839d66 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -844,7 +844,7 @@ "ibm": "IBM Cloud", "label": "Perspective", "ocp_all": "All OpenShift", - "ocp_ocp": "All cloud filtered by OpenShift" + "ocp_cloud": "All cloud filtered by OpenShift" } }, "page_cost_models": { diff --git a/src/pages/costModels/components/errorState.tsx b/src/pages/costModels/components/errorState.tsx index fd2a4c072..187e24b24 100644 --- a/src/pages/costModels/components/errorState.tsx +++ b/src/pages/costModels/components/errorState.tsx @@ -10,7 +10,7 @@ import { Title, TitleSizes, } from '@patternfly/react-core'; -import { ExclamationCircleIcon } from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon'; +import { ExclamationCircleIcon } from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon'; import global_DangerColor_100 from '@patternfly/react-tokens/dist/js/global_danger_color_100'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; diff --git a/src/pages/costModels/components/inputs/rateInput.tsx b/src/pages/costModels/components/inputs/rateInput.tsx index aa82e016d..ee7614d3d 100644 --- a/src/pages/costModels/components/inputs/rateInput.tsx +++ b/src/pages/costModels/components/inputs/rateInput.tsx @@ -6,7 +6,7 @@ import { TextInput, TextInputProps, } from '@patternfly/react-core'; -import { DollarSignIcon } from '@patternfly/react-icons/dist/js/icons/dollar-sign-icon'; +import { DollarSignIcon } from '@patternfly/react-icons/dist/esm/icons/dollar-sign-icon'; import React from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/src/pages/costModels/components/rateForm/rateForm.tsx b/src/pages/costModels/components/rateForm/rateForm.tsx index 64dae50ee..035727205 100644 --- a/src/pages/costModels/components/rateForm/rateForm.tsx +++ b/src/pages/costModels/components/rateForm/rateForm.tsx @@ -1,5 +1,5 @@ import { Button, ButtonVariant, FormGroup, Grid, GridItem, Radio, Switch } from '@patternfly/react-core'; -import { PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons/plus-circle-icon'; +import { PlusCircleIcon } from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; import { MetricHash } from 'api/metrics'; import { RateInputBase } from 'pages/costModels/components/inputs/rateInput'; import { Selector } from 'pages/costModels/components/inputs/selector'; diff --git a/src/pages/costModels/components/rateForm/taggingRatesForm.tsx b/src/pages/costModels/components/rateForm/taggingRatesForm.tsx index d615008b7..cec38b8dc 100644 --- a/src/pages/costModels/components/rateForm/taggingRatesForm.tsx +++ b/src/pages/costModels/components/rateForm/taggingRatesForm.tsx @@ -1,5 +1,5 @@ import { Button, ButtonVariant, Checkbox, FormGroup, Split, SplitItem } from '@patternfly/react-core'; -import { MinusCircleIcon } from '@patternfly/react-icons/dist/js/icons/minus-circle-icon'; +import { MinusCircleIcon } from '@patternfly/react-icons/dist/esm/icons/minus-circle-icon'; import { RateInputBase } from 'pages/costModels/components/inputs/rateInput'; import { SimpleInput } from 'pages/costModels/components/inputs/simpleInput'; import React from 'react'; diff --git a/src/pages/costModels/components/toolbar/primarySelector.tsx b/src/pages/costModels/components/toolbar/primarySelector.tsx index 53102b771..dfd93f410 100644 --- a/src/pages/costModels/components/toolbar/primarySelector.tsx +++ b/src/pages/costModels/components/toolbar/primarySelector.tsx @@ -1,5 +1,5 @@ import { Select, SelectOption } from '@patternfly/react-core'; -import { FilterIcon } from '@patternfly/react-icons/dist/js/icons/filter-icon'; +import { FilterIcon } from '@patternfly/react-icons/dist/esm/icons/filter-icon'; import { WithStateMachine } from 'pages/costModels/components/hoc/withStateMachine'; import { selectMachineState } from 'pages/costModels/components/logic/selectStateMachine'; import { Option } from 'pages/costModels/components/logic/types'; diff --git a/src/pages/costModels/components/warningIcon.tsx b/src/pages/costModels/components/warningIcon.tsx index 90d58e17a..bcac1de3c 100644 --- a/src/pages/costModels/components/warningIcon.tsx +++ b/src/pages/costModels/components/warningIcon.tsx @@ -1,5 +1,5 @@ import { Tooltip } from '@patternfly/react-core'; -import { WarningTriangleIcon } from '@patternfly/react-icons/dist/js/icons/warning-triangle-icon'; +import { WarningTriangleIcon } from '@patternfly/react-icons/dist/esm/icons/warning-triangle-icon'; import React from 'react'; interface WarningIconProps { diff --git a/src/pages/costModels/costModel/addSourceWizard.tsx b/src/pages/costModels/costModel/addSourceWizard.tsx index 22902a958..40897fa51 100644 --- a/src/pages/costModels/costModel/addSourceWizard.tsx +++ b/src/pages/costModels/costModel/addSourceWizard.tsx @@ -79,15 +79,14 @@ class AddSourceWizardBase extends React.Component { private hasSelections = () => { const { checked } = this.state; - let result = false; - const items = Object.keys(checked); - items.map(key => { - if (checked[key].selected && !checked[key].disabled) { + for (const item of Object.keys(checked)) { + if (checked[item].selected && !checked[item].disabled) { result = true; + break; } - }); + } return result; }; diff --git a/src/pages/costModels/costModel/assignSourcesModalToolbar.tsx b/src/pages/costModels/costModel/assignSourcesModalToolbar.tsx index 4e615e670..904cad597 100644 --- a/src/pages/costModels/costModel/assignSourcesModalToolbar.tsx +++ b/src/pages/costModels/costModel/assignSourcesModalToolbar.tsx @@ -9,7 +9,7 @@ import { ToolbarFilter, ToolbarItem, } from '@patternfly/react-core'; -import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon'; +import { SearchIcon } from '@patternfly/react-icons/dist/esm/icons/search-icon'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; import { Omit } from 'react-redux'; diff --git a/src/pages/costModels/costModel/dialog.tsx b/src/pages/costModels/costModel/dialog.tsx index 573128d9b..dfe5c19ec 100644 --- a/src/pages/costModels/costModel/dialog.tsx +++ b/src/pages/costModels/costModel/dialog.tsx @@ -1,5 +1,5 @@ import { Alert, Button, Modal, Title, TitleSizes } from '@patternfly/react-core'; -import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/js/icons/exclamation-triangle-icon'; +import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; diff --git a/src/pages/costModels/costModel/index.tsx b/src/pages/costModels/costModel/index.tsx index fc80a3c7a..83662ae00 100644 --- a/src/pages/costModels/costModel/index.tsx +++ b/src/pages/costModels/costModel/index.tsx @@ -8,7 +8,7 @@ import { Title, TitleSizes, } from '@patternfly/react-core'; -import { ErrorCircleOIcon } from '@patternfly/react-icons/dist/js/icons/error-circle-o-icon'; +import { ErrorCircleOIcon } from '@patternfly/react-icons/dist/esm/icons/error-circle-o-icon'; import Main from '@redhat-cloud-services/frontend-components/Main'; import PageHeader, { PageHeaderTitle } from '@redhat-cloud-services/frontend-components/PageHeader'; import { CostModel } from 'api/costModels'; diff --git a/src/pages/costModels/costModel/priceListTable.tsx b/src/pages/costModels/costModel/priceListTable.tsx index bfa5e48a6..df4073ee2 100644 --- a/src/pages/costModels/costModel/priceListTable.tsx +++ b/src/pages/costModels/costModel/priceListTable.tsx @@ -14,7 +14,7 @@ import { ToolbarItem, ToolbarItemVariant, } from '@patternfly/react-core'; -import { FileInvoiceDollarIcon } from '@patternfly/react-icons/dist/js/icons/file-invoice-dollar-icon'; +import { FileInvoiceDollarIcon } from '@patternfly/react-icons/dist/esm/icons/file-invoice-dollar-icon'; import { Unavailable } from '@redhat-cloud-services/frontend-components/Unavailable'; import { CostModel } from 'api/costModels'; import { MetricHash } from 'api/metrics'; diff --git a/src/pages/costModels/costModel/sourcesToolbar.tsx b/src/pages/costModels/costModel/sourcesToolbar.tsx index bc519cf25..819089c8a 100644 --- a/src/pages/costModels/costModel/sourcesToolbar.tsx +++ b/src/pages/costModels/costModel/sourcesToolbar.tsx @@ -11,7 +11,7 @@ import { ToolbarFilter, ToolbarItem, } from '@patternfly/react-core'; -import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon'; +import { SearchIcon } from '@patternfly/react-icons/dist/esm/icons/search-icon'; import { ReadOnlyTooltip } from 'pages/costModels/components/readOnlyTooltip'; import React from 'react'; diff --git a/src/pages/costModels/costModel/table.tsx b/src/pages/costModels/costModel/table.tsx index 05d12ec88..412647cf8 100644 --- a/src/pages/costModels/costModel/table.tsx +++ b/src/pages/costModels/costModel/table.tsx @@ -1,5 +1,5 @@ import { EmptyState, EmptyStateBody, EmptyStateIcon, Title, TitleSizes } from '@patternfly/react-core'; -import { DollarSignIcon } from '@patternfly/react-icons/dist/js/icons/dollar-sign-icon'; +import { DollarSignIcon } from '@patternfly/react-icons/dist/esm/icons/dollar-sign-icon'; import { CostModel } from 'api/costModels'; import { EmptyFilterState } from 'components/state/emptyFilterState/emptyFilterState'; import { addMultiValueQuery, removeMultiValueQuery } from 'pages/costModels/components/filterLogic'; diff --git a/src/pages/costModels/costModelsDetails/header.tsx b/src/pages/costModels/costModelsDetails/header.tsx index 4fb32704a..ca939803c 100644 --- a/src/pages/costModels/costModelsDetails/header.tsx +++ b/src/pages/costModels/costModelsDetails/header.tsx @@ -1,5 +1,5 @@ import { Button, ButtonVariant, Popover, TextContent, Title, TitleSizes } from '@patternfly/react-core'; -import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons/dist/js/icons/outlined-question-circle-icon'; +import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons/dist/esm/icons/outlined-question-circle-icon'; import React from 'react'; import { Trans, WithTranslation, withTranslation } from 'react-i18next'; import { connect } from 'react-redux'; diff --git a/src/pages/costModels/costModelsDetails/noCostModels.tsx b/src/pages/costModels/costModelsDetails/noCostModels.tsx index 08b3f3b38..2f970f24c 100644 --- a/src/pages/costModels/costModelsDetails/noCostModels.tsx +++ b/src/pages/costModels/costModelsDetails/noCostModels.tsx @@ -1,4 +1,4 @@ -import { PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons/plus-circle-icon'; +import { PlusCircleIcon } from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; import HookIntoProps from 'hook-into-props'; import { CreateCostModelButton } from 'pages/costModels/costModelsDetails/createCostModelButton'; import React from 'react'; diff --git a/src/pages/costModels/costModelsDetails/noMatchFound.tsx b/src/pages/costModels/costModelsDetails/noMatchFound.tsx index 7ec9c6cdf..95c5e7d31 100644 --- a/src/pages/costModels/costModelsDetails/noMatchFound.tsx +++ b/src/pages/costModels/costModelsDetails/noMatchFound.tsx @@ -1,4 +1,4 @@ -import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon'; +import { SearchIcon } from '@patternfly/react-icons/dist/esm/icons/search-icon'; import HookIntoProps from 'hook-into-props'; import { useTranslation } from 'react-i18next'; diff --git a/src/pages/costModels/costModelsDetails/utils/filters.tsx b/src/pages/costModels/costModelsDetails/utils/filters.tsx index 6a6da18a5..f219df670 100644 --- a/src/pages/costModels/costModelsDetails/utils/filters.tsx +++ b/src/pages/costModels/costModelsDetails/utils/filters.tsx @@ -10,7 +10,7 @@ import { ToolbarFilterProps, ToolbarProps, } from '@patternfly/react-core'; -import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon'; +import { SearchIcon } from '@patternfly/react-icons/dist/esm/icons/search-icon'; import HookIntoProps from 'hook-into-props'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; diff --git a/src/pages/costModels/costModelsDetails/utils/toolbar.tsx b/src/pages/costModels/costModelsDetails/utils/toolbar.tsx index 07d2b6879..a1e3e1d46 100644 --- a/src/pages/costModels/costModelsDetails/utils/toolbar.tsx +++ b/src/pages/costModels/costModelsDetails/utils/toolbar.tsx @@ -7,7 +7,7 @@ import { SelectProps, SelectVariant, } from '@patternfly/react-core'; -import { FilterIcon } from '@patternfly/react-icons/dist/js/icons/filter-icon'; +import { FilterIcon } from '@patternfly/react-icons/dist/esm/icons/filter-icon'; import HookIntoProps from 'hook-into-props'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; diff --git a/src/pages/costModels/createCostModelWizard/assignSourcesToolbar.tsx b/src/pages/costModels/createCostModelWizard/assignSourcesToolbar.tsx index 4e615e670..904cad597 100644 --- a/src/pages/costModels/createCostModelWizard/assignSourcesToolbar.tsx +++ b/src/pages/costModels/createCostModelWizard/assignSourcesToolbar.tsx @@ -9,7 +9,7 @@ import { ToolbarFilter, ToolbarItem, } from '@patternfly/react-core'; -import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon'; +import { SearchIcon } from '@patternfly/react-icons/dist/esm/icons/search-icon'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; import { Omit } from 'react-redux'; diff --git a/src/pages/costModels/createCostModelWizard/index.tsx b/src/pages/costModels/createCostModelWizard/index.tsx index b6344aa8b..283d139b0 100644 --- a/src/pages/costModels/createCostModelWizard/index.tsx +++ b/src/pages/costModels/createCostModelWizard/index.tsx @@ -1,6 +1,6 @@ import { Title, TitleSizes, Wizard, WizardStepFunctionType } from '@patternfly/react-core'; import { Button, Modal } from '@patternfly/react-core'; -import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/js/icons/exclamation-triangle-icon'; +import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon'; import { addCostModel } from 'api/costModels'; import { MetricHash } from 'api/metrics'; import { Rate } from 'api/rates'; diff --git a/src/pages/costModels/createCostModelWizard/markup.tsx b/src/pages/costModels/createCostModelWizard/markup.tsx index 070f85f86..9a632c742 100644 --- a/src/pages/costModels/createCostModelWizard/markup.tsx +++ b/src/pages/costModels/createCostModelWizard/markup.tsx @@ -17,10 +17,10 @@ import { TitleSizes, } from '@patternfly/react-core'; import { Form } from 'components/forms/form'; +import { styles } from 'pages/costModels/costModel/costCalc.styles'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; -import { styles } from '../costModel/costCalc.styles'; import { CostModelContext } from './context'; class MarkupWithDistribution extends React.Component { diff --git a/src/pages/costModels/createCostModelWizard/priceListTable.tsx b/src/pages/costModels/createCostModelWizard/priceListTable.tsx index 2d117c012..475679a9e 100644 --- a/src/pages/costModels/createCostModelWizard/priceListTable.tsx +++ b/src/pages/costModels/createCostModelWizard/priceListTable.tsx @@ -13,7 +13,7 @@ import { Title, TitleSizes, } from '@patternfly/react-core'; -import { PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons/plus-circle-icon'; +import { PlusCircleIcon } from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; import { MetricHash } from 'api/metrics'; import { EmptyFilterState } from 'components/state/emptyFilterState/emptyFilterState'; import { WithPriceListSearch } from 'pages/costModels/components/hoc/withPriceListSearch'; diff --git a/src/pages/costModels/createCostModelWizard/review.tsx b/src/pages/costModels/createCostModelWizard/review.tsx index 0b1504c73..7be7710a0 100644 --- a/src/pages/costModels/createCostModelWizard/review.tsx +++ b/src/pages/costModels/createCostModelWizard/review.tsx @@ -17,7 +17,7 @@ import { Title, TitleSizes, } from '@patternfly/react-core'; -import { OkIcon } from '@patternfly/react-icons/dist/js/icons/ok-icon'; +import { OkIcon } from '@patternfly/react-icons/dist/esm/icons/ok-icon'; import { RateTable } from 'pages/costModels/components/rateTable'; import { WarningIcon } from 'pages/costModels/components/warningIcon'; import React from 'react'; diff --git a/src/pages/state/noData/noDataState.tsx b/src/pages/state/noData/noDataState.tsx index 835b65174..55413908f 100644 --- a/src/pages/state/noData/noDataState.tsx +++ b/src/pages/state/noData/noDataState.tsx @@ -1,5 +1,5 @@ import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStateVariant, Title } from '@patternfly/react-core'; -import { FileInvoiceDollarIcon } from '@patternfly/react-icons/dist/js/icons/file-invoice-dollar-icon'; +import { FileInvoiceDollarIcon } from '@patternfly/react-icons/dist/esm/icons/file-invoice-dollar-icon'; import React from 'react'; import { WithTranslation, withTranslation } from 'react-i18next'; import { RouteComponentProps, withRouter } from 'react-router-dom'; diff --git a/src/pages/state/noProviders/noProvidersState.tsx b/src/pages/state/noProviders/noProvidersState.tsx index 8cf069644..83d2a1675 100644 --- a/src/pages/state/noProviders/noProvidersState.tsx +++ b/src/pages/state/noProviders/noProvidersState.tsx @@ -1,6 +1,6 @@ import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStateVariant, Title } from '@patternfly/react-core'; -import { ExternalLinkAltIcon } from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon'; -import { PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons/plus-circle-icon'; +import { ExternalLinkAltIcon } from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; +import { PlusCircleIcon } from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; import { ProviderType } from 'api/providers'; import CostIcon from 'components/icons/costIcon'; import React from 'react'; diff --git a/src/pages/views/components/dataToolbar/dataToolbar.tsx b/src/pages/views/components/dataToolbar/dataToolbar.tsx index 2f34ef118..7f80723fd 100644 --- a/src/pages/views/components/dataToolbar/dataToolbar.tsx +++ b/src/pages/views/components/dataToolbar/dataToolbar.tsx @@ -22,9 +22,9 @@ import { ToolbarItem, ToolbarToggleGroup, } from '@patternfly/react-core'; -import { ExportIcon } from '@patternfly/react-icons/dist/js/icons/export-icon'; -import { FilterIcon } from '@patternfly/react-icons/dist/js/icons/filter-icon'; -import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon'; +import { ExportIcon } from '@patternfly/react-icons/dist/esm/icons/export-icon'; +import { FilterIcon } from '@patternfly/react-icons/dist/esm/icons/filter-icon'; +import { SearchIcon } from '@patternfly/react-icons/dist/esm/icons/search-icon'; import { Org } from 'api/orgs/org'; import { orgUnitIdKey, orgUnitNameKey, Query, tagKey, tagPrefix } from 'api/queries/query'; import { ResourcePathsType } from 'api/resources/resource'; diff --git a/src/pages/views/details/awsDetails/awsDetails.tsx b/src/pages/views/details/awsDetails/awsDetails.tsx index 0653cd039..1f14c4507 100644 --- a/src/pages/views/details/awsDetails/awsDetails.tsx +++ b/src/pages/views/details/awsDetails/awsDetails.tsx @@ -21,6 +21,7 @@ import { RouteComponentProps } from 'react-router-dom'; import { createMapStateToProps, FetchStatus } from 'store/common'; import { awsProvidersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; +import { uiActions } from 'store/ui'; import { getIdKeyForGroupBy } from 'utils/computedReport/getComputedAwsReportItems'; import { ComputedReportItem, getUnsortedComputedReportItems } from 'utils/computedReport/getComputedReportItems'; @@ -41,6 +42,7 @@ interface AwsDetailsStateProps { interface AwsDetailsDispatchProps { fetchReport: typeof reportActions.fetchReport; + resetState: typeof uiActions.resetState; } interface AwsDetailsState { @@ -100,6 +102,9 @@ class AwsDetails extends React.Component { } public componentDidMount() { + const { resetState } = this.props; + + resetState(); // Clear cached API responses this.updateReport(); } @@ -478,6 +483,7 @@ const mapStateToProps = createMapStateToProps { } public componentDidMount() { + const { resetState } = this.props; + + resetState(); // Clear cached API responses this.updateReport(); } @@ -466,6 +471,7 @@ const mapStateToProps = createMapStateToProps { } public componentDidMount() { + const { resetState } = this.props; + + resetState(); // Clear cached API responses this.updateReport(); } @@ -465,6 +470,7 @@ const mapStateToProps = createMapStateToProps { } public componentDidMount() { + const { resetState } = this.props; + + resetState(); // Clear cached API responses this.updateReport(); } @@ -465,6 +470,7 @@ const mapStateToProps = createMapStateToProps { } public componentDidMount() { + const { resetState } = this.props; + + resetState(); // Clear cached API responses this.updateReport(); } @@ -513,6 +518,7 @@ const mapStateToProps = createMapStateToProps { } public componentDidMount() { + const { resetState } = this.props; + + resetState(); // Clear cached API responses this.updateReport(); } @@ -660,6 +665,7 @@ const mapStateToProps = createMapStateToProps { type OverviewOwnProps = RouteComponentProps & WithTranslation; +interface OverviewDispatchProps { + resetState: typeof uiActions.resetState; +} + interface OverviewStateProps { awsProviders: Providers; awsProvidersFetchStatus: FetchStatus; @@ -124,7 +134,7 @@ interface OverviewState { currentOcpPerspective?: string; } -type OverviewProps = OverviewOwnProps & OverviewStateProps; +type OverviewProps = OverviewOwnProps & OverviewStateProps & OverviewDispatchProps; // Ocp options const ocpOptions = [{ label: 'overview.perspective.ocp_all', value: 'all' }]; @@ -166,6 +176,10 @@ class OverviewBase extends React.Component { public state: OverviewState = { ...this.defaultState }; public componentDidMount() { + const { resetState } = this.props; + + resetState(); // Clear cached API responses + this.setState({ currentInfrastructurePerspective: this.getDefaultInfrastructurePerspective(), currentOcpPerspective: this.getDefaultOcpPerspective(), @@ -372,13 +386,15 @@ class OverviewBase extends React.Component { const hasData = hasCurrentMonthData(awsProviders) || hasPreviousMonthData(awsProviders); return hasData ? : noData; } else if (currentInfrastructurePerspective === InfrastructurePerspective.awsOcp) { - const hasData = hasCurrentMonthData(awsProviders) || hasPreviousMonthData(awsProviders); + const hasData = + hasCloudCurrentMonthData(awsProviders, ocpProviders) || hasCloudPreviousMonthData(awsProviders, ocpProviders); return hasData ? : noData; } else if (currentInfrastructurePerspective === InfrastructurePerspective.gcp) { const hasData = hasCurrentMonthData(gcpProviders) || hasPreviousMonthData(gcpProviders); return hasData ? : noData; } else if (currentInfrastructurePerspective === InfrastructurePerspective.gcpOcp) { - const hasData = hasCurrentMonthData(gcpProviders) || hasPreviousMonthData(gcpProviders); + const hasData = + hasCloudCurrentMonthData(gcpProviders, ocpProviders) || hasCloudPreviousMonthData(gcpProviders, ocpProviders); return hasData ? : noData; } else if (currentInfrastructurePerspective === InfrastructurePerspective.ibm) { const hasData = hasCurrentMonthData(ibmProviders) || hasPreviousMonthData(ibmProviders); @@ -387,7 +403,9 @@ class OverviewBase extends React.Component { const hasData = hasCurrentMonthData(azureProviders) || hasPreviousMonthData(azureProviders); return hasData ? : noData; } else if (currentInfrastructurePerspective === InfrastructurePerspective.azureOcp) { - const hasData = hasCurrentMonthData(azureProviders) || hasPreviousMonthData(azureProviders); + const hasData = + hasCloudCurrentMonthData(azureProviders, ocpProviders) || + hasCloudPreviousMonthData(azureProviders, ocpProviders); return hasData ? : noData; } else { return noData; @@ -653,6 +671,10 @@ const mapStateToProps = createMapStateToProps { - let result = false; +// eslint-disable-next-line no-shadow +const enum DataType { + currentMonthData = 'current_month_data', + hasData = 'has_data', + previousMonthData = 'previous_month_data', +} - if (providers && providers.data) { - for (const provider of providers.data) { - if (provider.current_month_data) { - result = true; +// Returns the OCP provider matching the given infrastructure uuid +const _getOcpProvider = (ocpProviders: Providers, uuid?: string) => { + let result; + + if (ocpProviders && ocpProviders.data) { + for (const provider of ocpProviders.data) { + if (provider.infrastructure && provider.infrastructure.uuid === uuid) { + result = provider; break; } } @@ -16,12 +23,12 @@ export const hasCurrentMonthData = (providers: Providers) => { }; // Ensure at least one source provider has data available -export const hasData = (providers: Providers) => { +const _hasData = (providers: Providers, dataType: DataType) => { let result = false; if (providers && providers.data) { for (const provider of providers.data) { - if (provider.has_data) { + if (provider[dataType]) { result = true; break; } @@ -30,13 +37,16 @@ export const hasData = (providers: Providers) => { return result; }; -// Ensure at least one source provider has data available for the previous month -export const hasPreviousMonthData = (providers: Providers) => { +// Ensure at least one cloud source provider has data available +const _hasCloudData = (providers: Providers, ocpProviders: Providers, dataType: DataType) => { let result = false; if (providers && providers.data) { for (const provider of providers.data) { - if (provider.previous_month_data) { + const ocpProvider = _getOcpProvider(ocpProviders, provider.uuid); + + // Ensure AWS provider is filtered by OpenShift and has OCP data + if (ocpProvider && ocpProvider[dataType]) { result = true; break; } @@ -44,3 +54,33 @@ export const hasPreviousMonthData = (providers: Providers) => { } return result; }; + +// Ensure at least one cloud source provider has data available for the current month (e.g., "AWS filtered by OpenShift") +export const hasCloudCurrentMonthData = (providers: Providers, ocpProviders: Providers) => { + return _hasCloudData(providers, ocpProviders, DataType.currentMonthData); +}; + +// Ensure at least one cloud source provider has data available (e.g., "AWS filtered by OpenShift") +export const hasCloudData = (providers: Providers, ocpProviders: Providers) => { + return _hasCloudData(providers, ocpProviders, DataType.hasData); +}; + +// Ensure at least one cloud source provider has data available for the previous month (e.g., "AWS filtered by OpenShift") +export const hasCloudPreviousMonthData = (providers: Providers, ocpProviders: Providers) => { + return _hasCloudData(providers, ocpProviders, DataType.previousMonthData); +}; + +// Ensure at least one source provider has data available for the current month +export const hasCurrentMonthData = (providers: Providers) => { + return _hasData(providers, DataType.currentMonthData); +}; + +// Ensure at least one source provider has data available +export const hasData = (providers: Providers) => { + return _hasData(providers, DataType.hasData); +}; + +// Ensure at least one source provider has data available for the previous month +export const hasPreviousMonthData = (providers: Providers) => { + return _hasData(providers, DataType.previousMonthData); +}; diff --git a/src/store/exports/exportReducer.ts b/src/store/exports/exportReducer.ts index 7b644e76e..25a56005c 100644 --- a/src/store/exports/exportReducer.ts +++ b/src/store/exports/exportReducer.ts @@ -1,6 +1,7 @@ import { Export } from 'api/exports/export'; import { AxiosError } from 'axios'; import { FetchStatus } from 'store/common'; +import { resetState } from 'store/ui/uiActions'; import { ActionType, getType } from 'typesafe-actions'; import { fetchExportFailure, fetchExportRequest, fetchExportSuccess } from './exportActions'; @@ -22,11 +23,15 @@ const defaultState: ExportState = { }; export type ExportAction = ActionType< - typeof fetchExportFailure | typeof fetchExportRequest | typeof fetchExportSuccess + typeof fetchExportFailure | typeof fetchExportRequest | typeof fetchExportSuccess | typeof resetState >; export function exportReducer(state = defaultState, action: ExportAction): ExportState { switch (action.type) { + case getType(resetState): + state = defaultState; + return state; + case getType(fetchExportRequest): return { ...state, diff --git a/src/store/forecasts/forecastReducer.ts b/src/store/forecasts/forecastReducer.ts index 1f74295b5..3e0477212 100644 --- a/src/store/forecasts/forecastReducer.ts +++ b/src/store/forecasts/forecastReducer.ts @@ -1,6 +1,7 @@ import { Forecast } from 'api/forecasts/forecast'; import { AxiosError } from 'axios'; import { FetchStatus } from 'store/common'; +import { resetState } from 'store/ui/uiActions'; import { ActionType, getType } from 'typesafe-actions'; import { fetchForecastFailure, fetchForecastRequest, fetchForecastSuccess } from './forecastActions'; @@ -22,11 +23,15 @@ const defaultState: ForecastState = { }; export type ForecastAction = ActionType< - typeof fetchForecastFailure | typeof fetchForecastRequest | typeof fetchForecastSuccess + typeof fetchForecastFailure | typeof fetchForecastRequest | typeof fetchForecastSuccess | typeof resetState >; export function forecastReducer(state = defaultState, action: ForecastAction): ForecastState { switch (action.type) { + case getType(resetState): + state = defaultState; + return state; + case getType(fetchForecastRequest): return { ...state, diff --git a/src/store/orgs/orgReducer.ts b/src/store/orgs/orgReducer.ts index 27a0a582c..b76feb23d 100644 --- a/src/store/orgs/orgReducer.ts +++ b/src/store/orgs/orgReducer.ts @@ -1,6 +1,7 @@ import { Org } from 'api/orgs/org'; import { AxiosError } from 'axios'; import { FetchStatus } from 'store/common'; +import { resetState } from 'store/ui/uiActions'; import { ActionType, getType } from 'typesafe-actions'; import { fetchOrgFailure, fetchOrgRequest, fetchOrgSuccess } from './orgActions'; @@ -21,10 +22,16 @@ const defaultState: OrgState = { errors: new Map(), }; -export type OrgAction = ActionType; +export type OrgAction = ActionType< + typeof fetchOrgFailure | typeof fetchOrgRequest | typeof fetchOrgSuccess | typeof resetState +>; export function orgReducer(state = defaultState, action: OrgAction): OrgState { switch (action.type) { + case getType(resetState): + state = defaultState; + return state; + case getType(fetchOrgRequest): return { ...state, diff --git a/src/store/reports/reportReducer.ts b/src/store/reports/reportReducer.ts index 6ccd4b963..d4798d3e1 100644 --- a/src/store/reports/reportReducer.ts +++ b/src/store/reports/reportReducer.ts @@ -1,6 +1,7 @@ import { Report } from 'api/reports/report'; import { AxiosError } from 'axios'; import { FetchStatus } from 'store/common'; +import { resetState } from 'store/ui/uiActions'; import { ActionType, getType } from 'typesafe-actions'; import { fetchReportFailure, fetchReportRequest, fetchReportSuccess } from './reportActions'; @@ -22,11 +23,15 @@ const defaultState: ReportState = { }; export type ReportAction = ActionType< - typeof fetchReportFailure | typeof fetchReportRequest | typeof fetchReportSuccess + typeof fetchReportFailure | typeof fetchReportRequest | typeof fetchReportSuccess | typeof resetState >; export function reportReducer(state = defaultState, action: ReportAction): ReportState { switch (action.type) { + case getType(resetState): + state = defaultState; + return state; + case getType(fetchReportRequest): return { ...state, diff --git a/src/store/resources/resourceReducer.ts b/src/store/resources/resourceReducer.ts index e5bcdb961..3b400987f 100644 --- a/src/store/resources/resourceReducer.ts +++ b/src/store/resources/resourceReducer.ts @@ -1,6 +1,7 @@ import { Resource } from 'api/resources/resource'; import { AxiosError } from 'axios'; import { FetchStatus } from 'store/common'; +import { resetState } from 'store/ui/uiActions'; import { ActionType, getType } from 'typesafe-actions'; import { fetchResourceFailure, fetchResourceRequest, fetchResourceSuccess } from './resourceActions'; @@ -22,11 +23,15 @@ const defaultState: ResourceState = { }; export type ResourceAction = ActionType< - typeof fetchResourceFailure | typeof fetchResourceRequest | typeof fetchResourceSuccess + typeof fetchResourceFailure | typeof fetchResourceRequest | typeof fetchResourceSuccess | typeof resetState >; export function resourceReducer(state = defaultState, action: ResourceAction): ResourceState { switch (action.type) { + case getType(resetState): + state = defaultState; + return state; + case getType(fetchResourceRequest): return { ...state, diff --git a/src/store/tags/tagReducer.ts b/src/store/tags/tagReducer.ts index 7a30c4abe..5ed43335f 100644 --- a/src/store/tags/tagReducer.ts +++ b/src/store/tags/tagReducer.ts @@ -1,6 +1,7 @@ import { Tag } from 'api/tags/tag'; import { AxiosError } from 'axios'; import { FetchStatus } from 'store/common'; +import { resetState } from 'store/ui/uiActions'; import { ActionType, getType } from 'typesafe-actions'; import { fetchTagFailure, fetchTagRequest, fetchTagSuccess } from './tagActions'; @@ -21,10 +22,16 @@ const defaultState: TagState = { errors: new Map(), }; -export type TagAction = ActionType; +export type TagAction = ActionType< + typeof fetchTagFailure | typeof fetchTagRequest | typeof fetchTagSuccess | typeof resetState +>; export function tagReducer(state = defaultState, action: TagAction): TagState { switch (action.type) { + case getType(resetState): + state = defaultState; + return state; + case getType(fetchTagRequest): return { ...state, diff --git a/src/store/ui/uiActions.ts b/src/store/ui/uiActions.ts index a31da43ee..dcad4da1b 100644 --- a/src/store/ui/uiActions.ts +++ b/src/store/ui/uiActions.ts @@ -1,7 +1,13 @@ +import { ThunkAction } from 'store/common'; import { createAction } from 'typesafe-actions'; export const closeProvidersModal = createAction('ui/close_providers_modal')(); - export const openProvidersModal = createAction('ui/open_providers_modal')(); - export const toggleSidebar = createAction('ui/toggle_sidebar')(); +export const resetState = createAction('ui/reset_state')(); + +export function resetReportState(): ThunkAction { + return dispatch => { + dispatch(resetState()); + }; +} diff --git a/test/transformTS.js b/test/transformTS.js index 763b987fd..d5956cea1 100644 --- a/test/transformTS.js +++ b/test/transformTS.js @@ -13,7 +13,7 @@ delete options.sourceMap; module.exports = { process(src, path) { - if (path.endsWith('.ts') || path.endsWith('.tsx')) { + if (path.endsWith('.ts') || path.endsWith('.tsx') || path.includes('@patternfly/react-icons/dist/esm')) { return tsc.transpile(src, options, path, []); } return src; diff --git a/yarn.lock b/yarn.lock index e4e878c52..a6924d52f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -416,11 +416,26 @@ "@formatjs/intl-localematcher" "0.2.19" tslib "^2.1.0" +"@formatjs/ecma402-abstract@1.9.7": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.7.tgz#92743737f6cfe16eb1666fe710121f8af26ecff5" + integrity sha512-Lu05JjSlL4QbXLiJHcljmWLSSKoxc4ed6aAz4ZPIJn7HsgzoObR4wKllFVcEWnIfiW8FIWITOZjXjoZ8MamSJA== + dependencies: + "@formatjs/intl-localematcher" "0.2.20" + tslib "^2.1.0" + "@formatjs/fast-memoize@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.1.1.tgz#3006b58aca1e39a98aca213356b42da5d173f26b" integrity sha512-mIqBr5uigIlx13eZTOPSEh2buDiy3BCdMYUtewICREQjbb4xarDiVWoXSnrERM7NanZ+0TAHNXSqDe6HpEFQUg== +"@formatjs/fast-memoize@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.2.0.tgz#1123bfcc5d21d761f15d8b1c32d10e1b6530355d" + integrity sha512-fObitP9Tlc31SKrPHgkPgQpGo4+4yXfQQITTCNH8AZdEqB7Mq4nPrjpUL/tNGN3lEeJcFxDbi0haX8HM7QvQ8w== + dependencies: + tslib "^2.1.0" + "@formatjs/icu-messageformat-parser@2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.0.1.tgz#a3b542542b92958f1cdd090f1cb475cb7cb4e21a" @@ -430,6 +445,15 @@ "@formatjs/icu-skeleton-parser" "1.2.2" tslib "^2.1.0" +"@formatjs/icu-messageformat-parser@2.0.10": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.0.10.tgz#aecf5714bc4a7fa57d04e4a51767c3f5a9ced17f" + integrity sha512-X1HTDTs0sdLVFFJLZuJ4+YfMMWv7/wGsoE7yIQkzKlck3HrAA/dBZDR1sOwcxH7Rz8NY1K+oUOkPe/f1sa7Q8g== + dependencies: + "@formatjs/ecma402-abstract" "1.9.7" + "@formatjs/icu-skeleton-parser" "1.2.11" + tslib "^2.1.0" + "@formatjs/icu-messageformat-parser@2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.0.2.tgz#93121e4cc1455f29566cd712072e3d8372ba52ee" @@ -456,6 +480,14 @@ "@formatjs/ecma402-abstract" "1.9.6" tslib "^2.1.0" +"@formatjs/icu-skeleton-parser@1.2.11": + version "1.2.11" + resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.2.11.tgz#187a632e18b851f529bbf673a440b4523b18863e" + integrity sha512-nvme882npz//T17BR5S1xdNqv10CSlHsaPZ1iUxVrDTlotQHcr7O5qkX6JjpQ6qPflTt2s4k0W9nkMcFIfDuFg== + dependencies: + "@formatjs/ecma402-abstract" "1.9.7" + tslib "^2.1.0" + "@formatjs/icu-skeleton-parser@1.2.2": version "1.2.2" resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.2.2.tgz#6e9a6eff16e3c7b69d67d40b292d4b499e37228e" @@ -480,6 +512,15 @@ "@formatjs/ecma402-abstract" "1.8.0" tslib "^2.1.0" +"@formatjs/intl-displaynames@5.2.2": + version "5.2.2" + resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-5.2.2.tgz#7e5c9b99934ef9b8332e8a8ba1b42d0c08e13900" + integrity sha512-Xyl4KNhBUWroKzmOX7qXI008VazJMHZbebpRXhoQgjmFPGc87QBVjYcfwEmGHlRQgJ4L/bvQ6GNiN6b2Y96xUg== + dependencies: + "@formatjs/ecma402-abstract" "1.9.7" + "@formatjs/intl-localematcher" "0.2.20" + tslib "^2.1.0" + "@formatjs/intl-listformat@6.1.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-6.1.0.tgz#ab3669c01a88ac6c91e7e602ed5de282466af08c" @@ -488,6 +529,15 @@ "@formatjs/ecma402-abstract" "1.8.0" tslib "^2.1.0" +"@formatjs/intl-listformat@6.3.2": + version "6.3.2" + resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-6.3.2.tgz#50602b66b097b5f774ab81e737bf7d715fac7e60" + integrity sha512-9RiSmg8VPN+82c3MlHxQVX9pD20KcIyjOeDJBM9K9uieLR4X3v0RJneXj2yv6WyhHNhHvrhPmrWFjQYTowJLzQ== + dependencies: + "@formatjs/ecma402-abstract" "1.9.7" + "@formatjs/intl-localematcher" "0.2.20" + tslib "^2.1.0" + "@formatjs/intl-localematcher@0.2.19": version "0.2.19" resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.2.19.tgz#a4ade690b122cc719b669808063e2a04414622f7" @@ -495,6 +545,13 @@ dependencies: tslib "^2.1.0" +"@formatjs/intl-localematcher@0.2.20": + version "0.2.20" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.2.20.tgz#782aef53d1c1b6112ee67468dc59f9b8d1ba7b17" + integrity sha512-/Ro85goRZnCojzxOegANFYL0LaDIpdPjAukR7xMTjOtRx+3yyjR0ifGTOW3/Kjhmab3t6GnyHBYWZSudxEOxPA== + dependencies: + tslib "^2.1.0" + "@formatjs/intl@1.10.8": version "1.10.8" resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-1.10.8.tgz#879a7e15d7ab6f5f6063895edd045d8f91ff07b3" @@ -508,6 +565,18 @@ intl-messageformat "9.6.14" tslib "^2.1.0" +"@formatjs/intl@1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-1.14.0.tgz#320f033647bc4139277adaa2b25cc57c1e3d4912" + integrity sha512-Oh3xa8WE8wjQGsBjkhgzpIww+liNyiMKkRGkAJWFAEZ+ZfUc/16thUD4Yp9HSM9TmEs7ibBIBW7Uz5785D/rmQ== + dependencies: + "@formatjs/ecma402-abstract" "1.9.7" + "@formatjs/fast-memoize" "1.2.0" + "@formatjs/intl-displaynames" "5.2.2" + "@formatjs/intl-listformat" "6.3.2" + intl-messageformat "9.9.0" + tslib "^2.1.0" + "@formatjs/ts-transformer@3.3.12": version "3.3.12" resolved "https://registry.yarnpkg.com/@formatjs/ts-transformer/-/ts-transformer-3.3.12.tgz#f3630b77eee7563e8b2a6ba01a20a53e656c2a44" @@ -848,6 +917,15 @@ "@redhat-cloud-services/frontend-components-utilities" "*" redux-promise-middleware "6.1.2" +"@redhat-cloud-services/frontend-components-translations@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@redhat-cloud-services/frontend-components-translations/-/frontend-components-translations-3.2.2.tgz#bb4b39514b80bfb1722958f42dfb4c5b3ea5938d" + integrity sha512-j2npAgsvP5CCMppY9/esKdbt7ANto9ZKlZm31cqPCI2e78G3YU8iDrxgvCGNG7UwLWU7n2uLwBBsNrRIm9nB+g== + dependencies: + react-intl "^5.17.4" + optionalDependencies: + "@redhat-cloud-services/frontend-components-utilities" ">=3.0.0" + "@redhat-cloud-services/frontend-components-utilities@*", "@redhat-cloud-services/frontend-components-utilities@>=3.0.0", "@redhat-cloud-services/frontend-components-utilities@^3.2.3": version "3.2.3" resolved "https://registry.yarnpkg.com/@redhat-cloud-services/frontend-components-utilities/-/frontend-components-utilities-3.2.3.tgz#786cd0f980d5afd1b40f0844f3c676a8aa50e94c" @@ -1313,6 +1391,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@17": + version "17.0.18" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.18.tgz#4109cbbd901be9582e5e39e3d77acd7b66bb7fbe" + integrity sha512-YTLgu7oS5zvSqq49X5Iue5oAbVGhgPc5Au29SJC4VeE17V6gASoOxVkUDy9pXFMRFxCWCD9fLeweNFizo3UzOg== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/react@17.0.2": version "17.0.2" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.2.tgz#3de24c4efef902dd9795a49c75f760cbe4f7a5a8" @@ -2757,6 +2844,11 @@ commander@^4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.1.0.tgz#db36e3e66edf24ff591d639862c6ab2c52664362" + integrity sha512-mf45ldcuHSYShkplHHGKWb4TrmwQadxOn7v4WuhDJy0ZVoY5JFajaRDKD0PNe5qXzBX0rhovjTnP6Kz9LETcuA== + comment-parser@1.1.6-beta.0: version "1.1.6-beta.0" resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.1.6-beta.0.tgz#57e503b18d0a5bd008632dcc54b1f95c2fffe8f6" @@ -5098,6 +5190,15 @@ intl-messageformat@9.6.14: "@formatjs/icu-messageformat-parser" "2.0.2" tslib "^2.1.0" +intl-messageformat@9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-9.9.0.tgz#83b05b7de934f3ac47e0805a24bab3bc41f13783" + integrity sha512-5+XCcCHdO55A57Emrfd5bhZ0OhB0Kc2SJCe7pFJ4hK/xYgtMteA8R+L7qnHyE0EDuD8tlNQG3TzjULKd/Zqebw== + dependencies: + "@formatjs/fast-memoize" "1.2.0" + "@formatjs/icu-messageformat-parser" "2.0.10" + tslib "^2.1.0" + invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -7586,6 +7687,20 @@ react-intl@5.17.7: intl-messageformat "9.6.14" tslib "^2.1.0" +react-intl@^5.17.4: + version "5.20.9" + resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-5.20.9.tgz#ca086e5c4d800edb9dab5b7a236842106b99ac41" + integrity sha512-nObPjUkECRMjgmXKfP2OehvloosUPeneXK5+hntu1liig/yfyJ2i37HFFKyzStK6wynwJARwFBgjPQQDd1oLzw== + dependencies: + "@formatjs/intl" "1.14.0" + "@formatjs/intl-displaynames" "5.2.2" + "@formatjs/intl-listformat" "6.3.2" + "@types/hoist-non-react-statics" "^3.3.1" + "@types/react" "17" + hoist-non-react-statics "^3.3.2" + intl-messageformat "9.9.0" + tslib "^2.1.0" + react-is@^16.12.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"