diff --git a/.codecov.yml b/.codecov.yml index f030593a9..9ef75eae5 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,28 +1,28 @@ coverage: precision: 2 round: down - range: "55...95" + range: '55...95' status: project: default: - target: "60%" + target: '60%' patch: default: off changes: default: off comment: - layout: "header, reach, diff, flags, files, footer" + layout: 'header, reach, diff, flags, files, footer' behavior: default require_changes: no require_base: no require_head: yes ignore: - - "src/common/*" - - "src/setupTests.js" - - "src/**/*store.js" - - "src/redux/index.js" - - "src/components/app.js" - - "src/redux/middleware/*" + - 'src/common/*' + - 'src/setupTests.js' + - 'src/**/*store.js' + - 'src/redux/index.js' + - 'src/components/app.js' + - 'src/redux/middleware/*' diff --git a/.eslintrc b/.eslintrc index ff63cba5c..955437a4b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -15,15 +15,7 @@ "parserOptions": { "ecmaVersion": 2022 }, - "plugins": [ - "import", - "jest", - "jsdoc", - "json", - "node", - "prettier", - "react" - ], + "plugins": ["import", "jest", "jsdoc", "json", "node", "prettier", "react"], "settings": { "import/external-module-folders": ["public"], "jsdoc": {} @@ -34,10 +26,7 @@ "shallowComponent": "readonly" }, "rules": { - "arrow-parens": [ - "error", - "as-needed" - ], + "arrow-parens": ["error", "as-needed"], "class-methods-use-this": 1, "comma-dangle": 0, "consistent-return": 1, @@ -59,10 +48,7 @@ "import/no-named-as-default": 0, "import/no-named-as-default-member": 0, "jest/no-done-callback": 0, - "jest/no-standalone-expect": [ - 2, - { "additionalTestBlockFunctions": ["skipIt"] } - ], + "jest/no-standalone-expect": [2, { "additionalTestBlockFunctions": ["skipIt"] }], "jest/prefer-to-have-length": 0, "jsdoc/check-tag-names": [ 2, @@ -115,38 +101,47 @@ "no-lonely-if": 1, "no-plusplus": 0, "no-promise-executor-return": 1, - "no-restricted-exports": [1, {"restrictedNamedExports": []}], - "no-restricted-properties": [0, {"object": "Math", "property": "pow"}], + "no-restricted-exports": [1, { "restrictedNamedExports": [] }], + "no-restricted-properties": [0, { "object": "Math", "property": "pow" }], "no-underscore-dangle": 0, "no-unsafe-optional-chaining": 1, "prefer-exponentiation-operator": 0, "prefer-promise-reject-errors": 1, "prefer-regex-literals": 0, "react/forbid-prop-types": 0, - "react/function-component-definition": [2, { "namedComponents": "arrow-function", "unnamedComponents": "arrow-function" }], + "react/function-component-definition": [ + 2, + { "namedComponents": "arrow-function", "unnamedComponents": "arrow-function" } + ], "react/jsx-curly-newline": 0, "react/jsx-filename-extension": 0, - "react/jsx-fragments": [ 1, "element" ], + "react/jsx-fragments": [1, "element"], "react/jsx-props-no-spreading": 0, "react/jsx-one-expression-per-line": 0, "react/jsx-no-constructed-context-values": 1, "react/no-unused-prop-types": 1, "react/no-unstable-nested-components": 0, "react/jsx-no-useless-fragment": 1, - "react/state-in-constructor": [ 1, "never" ], + "react/state-in-constructor": [1, "never"], "space-before-function-paren": 0, "jsx-a11y/anchor-is-valid": 1, - "jsx-a11y/label-has-associated-control": [ 2, { - "labelComponents": ["CustomInputLabel"], - "labelAttributes": ["label"], - "controlComponents": ["CustomInput"], - "depth": 3 - }], - "jsx-a11y/label-has-for": [ 2, { - "components": [ "Label" ], - "required": { - "some": [ "nesting", "id" ] + "jsx-a11y/label-has-associated-control": [ + 2, + { + "labelComponents": ["CustomInputLabel"], + "labelAttributes": ["label"], + "controlComponents": ["CustomInput"], + "depth": 3 + } + ], + "jsx-a11y/label-has-for": [ + 2, + { + "components": ["Label"], + "required": { + "some": ["nesting", "id"] + } } - }] + ] } } diff --git a/.github/ISSUE_TEMPLATE/Bug Report.md b/.github/ISSUE_TEMPLATE/Bug Report.md index 056bdc7e8..f0a9e483b 100644 --- a/.github/ISSUE_TEMPLATE/Bug Report.md +++ b/.github/ISSUE_TEMPLATE/Bug Report.md @@ -1,28 +1,37 @@ --- name: Bug report about: Create a report to help us improve - --- ## Bug Description: + ### Expected behavior + + ... ### Actual behavior + + ... ### Steps to reproduce + + 1. 1. ## Additional Context + ### Version Information + + ... diff --git a/.github/ISSUE_TEMPLATE/Feature Request.md b/.github/ISSUE_TEMPLATE/Feature Request.md index 06d18716d..35e43d8a2 100644 --- a/.github/ISSUE_TEMPLATE/Feature Request.md +++ b/.github/ISSUE_TEMPLATE/Feature Request.md @@ -1,27 +1,34 @@ --- name: Feature request about: Suggest an idea for this project - --- ## Feature description + As user X, I want Y to happen so that Z. ### Is your feature request related to a problem? + + ... ### Describe the solution you'd like + + ... -___ + +--- ## Acceptance Criteria + - [ ] Verify that users can X Y Z -___ +--- ## Additional context + -... +... diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d057a4501..4fd161735 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,11 +1,14 @@ ## What's included + + ... ## How to test + ## Example + + ... ## Updates issue/story + diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a11a51334..dc5dd4754 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,17 +6,17 @@ updates: interval: monthly day: monday open-pull-requests-limit: 3 - target-branch: "main" + target-branch: 'main' versioning-strategy: increase allow: - dependency-type: direct ignore: - - dependency-name: "*patternfly*" - - dependency-name: "*i18next*" - - dependency-name: "react-router*" - - dependency-name: "quipudocs" + - dependency-name: '*patternfly*' + - dependency-name: '*i18next*' + - dependency-name: 'react-router*' + - dependency-name: 'quipudocs' labels: - - "build" + - 'build' - package-ecosystem: github-actions directory: / @@ -24,6 +24,6 @@ updates: interval: monthly day: monday open-pull-requests-limit: 2 - target-branch: "main" + target-branch: 'main' labels: - - "build" + - 'build' diff --git a/.github/workflows/commit_lint.yml b/.github/workflows/commit_lint.yml index 3c7fe4af4..b02dcd2fd 100644 --- a/.github/workflows/commit_lint.yml +++ b/.github/workflows/commit_lint.yml @@ -1,6 +1,5 @@ name: Commit lint -on: - pull_request +on: pull_request env: BRANCH: ${{ github.base_ref }} diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f25781b85..1604ad8c1 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -3,7 +3,7 @@ on: push: branches: [master, main, dev**] tags: - - "*" + - '*' pull_request: env: COV_NODE_VERSION: 18 @@ -58,7 +58,7 @@ jobs: uses: ncipollo/release-action@v1.13.0 if: ${{ success() && startsWith(matrix.node-version, env.COV_NODE_VERSION) && startsWith(github.ref, 'refs/tags/') }} with: - artifacts: "${{ env.UPSTREAM_TAR }}.gz" + artifacts: '${{ env.UPSTREAM_TAR }}.gz' # set allow updates so we can create releases to trigger this allowUpdates: true # don't override what's set on the release diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c39dec2..4ee407cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,326 +4,358 @@ All notable changes to this project will be documented in this file. ## 1.6.1 (2023-11-10) - ### Documentation -* stop recommending the "dev" branch (b8f1f6f) -* update CONTRIBUTING release instructions (370b068) + +- stop recommending the "dev" branch (b8f1f6f) +- update CONTRIBUTING release instructions (370b068) ### Chores -* **deps-dev** eslint-plugin-jsdoc from 46.5.0 to 46.8.2 (#250) (b525cf9) -* **deps-dev** cspell from 7.0.1 to 7.3.8 (#253) (42191ed) -* **deps** actions/checkout from 3 to 4 (#247) (b92ea2a) + +- **deps-dev** eslint-plugin-jsdoc from 46.5.0 to 46.8.2 (#250) (b525cf9) +- **deps-dev** cspell from 7.0.1 to 7.3.8 (#253) (42191ed) +- **deps** actions/checkout from 3 to 4 (#247) (b92ea2a) ### Bug Fixes -* **rhacs** use appropriate naming conventions (#258) (28ee440) -## 1.6.0 (2023-10-17) +- **rhacs** use appropriate naming conventions (#258) (28ee440) +## 1.6.0 (2023-10-17) ### Features -* **acs** add support for acs data source (#251) (e1faafc) + +- **acs** add support for acs data source (#251) (e1faafc) ### Code Refactoring -* **scans** discovery-423 disable scan merge reports (#243) (12fc5f4) + +- **scans** discovery-423 disable scan merge reports (#243) (12fc5f4) ### Chores -* **deps-dev** bump eslint from 8.47.0 to 8.50.0 (#246) (62cec9e) -* **deps-dev** jest-environment-jsdom from 29.6.2 to 29.7.0 (#245) (10949a9) -* **deps-dev** jest-resolve from 29.6.2 to 29.7.0 (#244) (69ec992) -* **deps** ncipollo/release-action from 1.12.0 to 1.13.0 (#242) (d43ab54) -* **deps** npm updates (#238) (b65a9a3) + +- **deps-dev** bump eslint from 8.47.0 to 8.50.0 (#246) (62cec9e) +- **deps-dev** jest-environment-jsdom from 29.6.2 to 29.7.0 (#245) (10949a9) +- **deps-dev** jest-resolve from 29.6.2 to 29.7.0 (#244) (69ec992) +- **deps** ncipollo/release-action from 1.12.0 to 1.13.0 (#242) (d43ab54) +- **deps** npm updates (#238) (b65a9a3) ### Bug Fixes -* **scripts** allow podman and docker (#237) (ae03ebf) -## 1.5.1 (2023-08-23) +- **scripts** allow podman and docker (#237) (ae03ebf) +## 1.5.1 (2023-08-23) ### Code Refactoring -* **testing** DISCOVERY-280 Add attributes to aid UI tests (#235) (1fe16d5) + +- **testing** DISCOVERY-280 Add attributes to aid UI tests (#235) (1fe16d5) ### Chores -* **deps-dev** bump eslint-config-prettier from 8.8.0 to 8.9.0 (#233) (2c0dbe4) -## 1.5.0 (2023-08-02) +- **deps-dev** bump eslint-config-prettier from 8.8.0 to 8.9.0 (#233) (2c0dbe4) +## 1.5.0 (2023-08-02) ### Documentation -* rename master branch to main (779284f) + +- rename master branch to main (779284f) ### Code Refactoring -* **testing** react testing, handler context wrappers (#229) (0a14eca) -* **testing** migrate from enzyme (#227) (0e4f798) + +- **testing** react testing, handler context wrappers (#229) (0a14eca) +- **testing** migrate from enzyme (#227) (0e4f798) ### Chores -* **deps-dev** eslint-plugin-jest from 27.2.2 to 27.2.3 (#232) (45aedde) -* **deps-dev** bump babel-loader from 9.1.2 to 9.1.3 (#231) (8a8fe46) -* **dependabot** open pr limit, target branch (#226) (6244d3b) -* **deps** npm updates (#226) (1b4bb76) -* **deps-dev** bump webpack from 5.86.0 to 5.88.1 (#225) (1a58b43) -* remove unused Jenkinsfile (8c71990) + +- **deps-dev** eslint-plugin-jest from 27.2.2 to 27.2.3 (#232) (45aedde) +- **deps-dev** bump babel-loader from 9.1.2 to 9.1.3 (#231) (8a8fe46) +- **dependabot** open pr limit, target branch (#226) (6244d3b) +- **deps** npm updates (#226) (1b4bb76) +- **deps-dev** bump webpack from 5.86.0 to 5.88.1 (#225) (1a58b43) +- remove unused Jenkinsfile (8c71990) ### Builds -* **babel** update presets, targets (06461bd) -## 1.4.0 (2023-06-29) +- **babel** update presets, targets (06461bd) +## 1.4.0 (2023-06-29) ### Features -* **pageLayout** discovery-334 update to pf4 (#210) (e670215) + +- **pageLayout** discovery-334 update to pf4 (#210) (e670215) ### Documentation -* **readme,contributing** discovery-330 in-depth workflows (#214) (2cdc80a) + +- **readme,contributing** discovery-330 in-depth workflows (#214) (2cdc80a) ### Chores -* **deps** codecov/codecov-action from 3.1.3 to 3.1.4 (#211) (49d468a) + +- **deps** codecov/codecov-action from 3.1.3 to 3.1.4 (#211) (49d468a) ### Builds -* **docs** DISCOVERY-357 Stop building docs pages (7b0fa0f) -* **deps** discovery-330 core npm script (#213) (2dec3d5) -* **webpack** discovery-334 webpack 5 (#209) (2fd67e6) + +- **docs** DISCOVERY-357 Stop building docs pages (7b0fa0f) +- **deps** discovery-330 core npm script (#213) (2dec3d5) +- **webpack** discovery-334 webpack 5 (#209) (2fd67e6) ### Bug Fixes -* **formGroup** discovery-330 pf id to fieldId (#217) (33b43de) -* **deps** discovery-330 resolve test warnings (#216) (20b3303) -* **deps** discovery-330 pf react-core update (#216) (f72808b) -* **deps** discovery-330 npm updates (#216) (6245917) -* **createCredential** DISCOVERY-363 Use ssh_passphrase (#221) (ccd62b7) -* **pageLayout** DISCOVERY-357 remove quipudocs links (91ce87f) + +- **formGroup** discovery-330 pf id to fieldId (#217) (33b43de) +- **deps** discovery-330 resolve test warnings (#216) (20b3303) +- **deps** discovery-330 pf react-core update (#216) (f72808b) +- **deps** discovery-330 npm updates (#216) (6245917) +- **createCredential** DISCOVERY-363 Use ssh_passphrase (#221) (ccd62b7) +- **pageLayout** DISCOVERY-357 remove quipudocs links (91ce87f) ## [1.3.0](https://github.com/quipucords/quipucords-ui/compare/6ff43b4e466bd75de36f4533d4e0255f9a1b47b9...59b2e37f3fe225c346f2e35174571dcb84bfc98d) (2023-06-07) ### Features -* **scans** discovery-76 adds delete functionality ([#208](https://github.com/quipucords/quipucords-ui/pull/208)) ([59b2e37](https://github.com/quipucords/quipucords-ui/commit/59b2e37f3fe225c346f2e35174571dcb84bfc98d)) + +- **scans** discovery-76 adds delete functionality ([#208](https://github.com/quipucords/quipucords-ui/pull/208)) ([59b2e37](https://github.com/quipucords/quipucords-ui/commit/59b2e37f3fe225c346f2e35174571dcb84bfc98d)) ### Documentation -* **CONTRIBUTING.md** workaround for ERR_OSSL_EVP_UNSUPPORTED ([#205](https://github.com/quipucords/quipucords-ui/pull/205)) ([a2f4151](https://github.com/quipucords/quipucords-ui/commit/a2f4151168be0e841000f8ee70db92582f124d63)) + +- **CONTRIBUTING.md** workaround for ERR_OSSL_EVP_UNSUPPORTED ([#205](https://github.com/quipucords/quipucords-ui/pull/205)) ([a2f4151](https://github.com/quipucords/quipucords-ui/commit/a2f4151168be0e841000f8ee70db92582f124d63)) ### Chores -* **deps** codecov/codecov-action from 3.1.1 to 3.1.3 ([#202](https://github.com/quipucords/quipucords-ui/pull/202)) ([8d2713a](https://github.com/quipucords/quipucords-ui/commit/8d2713aa79d421ee84e61205225fc980b9ed56f3)) -* **deps-dev** changelog-light from 0.2.3 to 0.3.0 ([#199](https://github.com/quipucords/quipucords-ui/pull/199)) ([258adcc](https://github.com/quipucords/quipucords-ui/commit/258adcc4c703b42d40150cffc5cfbe4b3635bc68)) + +- **deps** codecov/codecov-action from 3.1.1 to 3.1.3 ([#202](https://github.com/quipucords/quipucords-ui/pull/202)) ([8d2713a](https://github.com/quipucords/quipucords-ui/commit/8d2713aa79d421ee84e61205225fc980b9ed56f3)) +- **deps-dev** changelog-light from 0.2.3 to 0.3.0 ([#199](https://github.com/quipucords/quipucords-ui/pull/199)) ([258adcc](https://github.com/quipucords/quipucords-ui/commit/258adcc4c703b42d40150cffc5cfbe4b3635bc68)) ## [1.2.0](https://github.com/quipucords/quipucords-ui/compare/6cee2723944d9bc7b4b3ded6aca9d5650713fe28...a7e1bddedca77f2ad8f95a8af2e0e858ee6a98ed) (2023-04-14) ### Features -* **ansible-controller** add support for ansible data source ([45cee58](https://github.com/quipucords/quipucords-ui/commit/45cee588cdf69395b825b88723e93d76aaa3619d)) + +- **ansible-controller** add support for ansible data source ([45cee58](https://github.com/quipucords/quipucords-ui/commit/45cee588cdf69395b825b88723e93d76aaa3619d)) ### Chores -* **build** nodejs 14 to 16 ([#197](https://github.com/quipucords/quipucords-ui/pull/197)) ([30bdc9f](https://github.com/quipucords/quipucords-ui/commit/30bdc9f118033ecfd3e852e40d4765ee48c1780a)) -* **deps** ncipollo/release-action from 1.11.2 to 1.12.0 ([#196](https://github.com/quipucords/quipucords-ui/pull/196)) ([823780e](https://github.com/quipucords/quipucords-ui/commit/823780ec9911aaa35581b9c1fde561d0221120d0)) -* **deps-dev** changelog-light from 0.2.1 to 0.2.3 ([#195](https://github.com/quipucords/quipucords-ui/pull/195)) ([b28e1a3](https://github.com/quipucords/quipucords-ui/commit/b28e1a31055433b3149ce2c81606c8dff400503e)) -* **deps** ncipollo/release-action from 1.10.0 to 1.11.2 ([#193](https://github.com/quipucords/quipucords-ui/pull/193)) ([f6e1464](https://github.com/quipucords/quipucords-ui/commit/f6e1464c40d7eec70d6bcc5deb238d83a18734b7)) + +- **build** nodejs 14 to 16 ([#197](https://github.com/quipucords/quipucords-ui/pull/197)) ([30bdc9f](https://github.com/quipucords/quipucords-ui/commit/30bdc9f118033ecfd3e852e40d4765ee48c1780a)) +- **deps** ncipollo/release-action from 1.11.2 to 1.12.0 ([#196](https://github.com/quipucords/quipucords-ui/pull/196)) ([823780e](https://github.com/quipucords/quipucords-ui/commit/823780ec9911aaa35581b9c1fde561d0221120d0)) +- **deps-dev** changelog-light from 0.2.1 to 0.2.3 ([#195](https://github.com/quipucords/quipucords-ui/pull/195)) ([b28e1a3](https://github.com/quipucords/quipucords-ui/commit/b28e1a31055433b3149ce2c81606c8dff400503e)) +- **deps** ncipollo/release-action from 1.10.0 to 1.11.2 ([#193](https://github.com/quipucords/quipucords-ui/pull/193)) ([f6e1464](https://github.com/quipucords/quipucords-ui/commit/f6e1464c40d7eec70d6bcc5deb238d83a18734b7)) ### Bug Fixes -* script for stage container ([a7e1bdd](https://github.com/quipucords/quipucords-ui/commit/a7e1bddedca77f2ad8f95a8af2e0e858ee6a98ed)) + +- script for stage container ([a7e1bdd](https://github.com/quipucords/quipucords-ui/commit/a7e1bddedca77f2ad8f95a8af2e0e858ee6a98ed)) ## [1.1.1](https://github.com/quipucords/quipucords-ui/compare/e6537bd5eb5c4cc87a804d69f8155d0bdbda1834...62ced03f639c1f6eeb5285b2528fc524fa0ffd4f) (2022-11-23) ### Bug Fixes -* **addSourceWizard** discovery-178 sslCert default (#189) (e6537bd) -## [1.1.0](https://github.com/quipucords/quipucords-ui/compare/edc4065f6786b9c332756b2b2a0abbfa70780ad1...1ac30164a170229d95bbacc01169b7674ad5b407) (2022-11-08) +- **addSourceWizard** discovery-178 sslCert default (#189) (e6537bd) + +## [1.1.0](https://github.com/quipucords/quipucords-ui/compare/edc4065f6786b9c332756b2b2a0abbfa70780ad1...1ac30164a170229d95bbacc01169b7674ad5b407) (2022-11-08) ### Features -* **addSource,createCredential** discovery-203 openshift ([#185](https://github.com/quipucords/quipucords-ui/pull/185)) ([1ac3016](https://github.com/quipucords/quipucords-ui/commit/1ac30164a170229d95bbacc01169b7674ad5b407)) -* **viewContext** expose inferred context ([#184](https://github.com/quipucords/quipucords-ui/pull/184)) ([fb57dab](https://github.com/quipucords/quipucords-ui/commit/fb57dab7809a36bfc3a762df37b325c158534d81)) + +- **addSource,createCredential** discovery-203 openshift ([#185](https://github.com/quipucords/quipucords-ui/pull/185)) ([1ac3016](https://github.com/quipucords/quipucords-ui/commit/1ac30164a170229d95bbacc01169b7674ad5b407)) +- **viewContext** expose inferred context ([#184](https://github.com/quipucords/quipucords-ui/pull/184)) ([fb57dab](https://github.com/quipucords/quipucords-ui/commit/fb57dab7809a36bfc3a762df37b325c158534d81)) ### Code Refactoring -* **createCredentialDialog** class to function, hooks ([#184](https://github.com/quipucords/quipucords-ui/pull/184)) ([61c7fec](https://github.com/quipucords/quipucords-ui/commit/61c7fec821fe6102907a59dd30ceb58146b1a46b)) + +- **createCredentialDialog** class to function, hooks ([#184](https://github.com/quipucords/quipucords-ui/pull/184)) ([61c7fec](https://github.com/quipucords/quipucords-ui/commit/61c7fec821fe6102907a59dd30ceb58146b1a46b)) ### Bug Fixes -* **createCredentialDialog** locale strings ([#185](https://github.com/quipucords/quipucords-ui/pull/185)) ([8490199](https://github.com/quipucords/quipucords-ui/commit/8490199f95798ea7d30e63b1fc83ff4cc688ef56)) -* **scanJobsList** minor test correction ([#184](https://github.com/quipucords/quipucords-ui/pull/184)) ([6adf7e3](https://github.com/quipucords/quipucords-ui/commit/6adf7e3e313ba40722f9bbc6aeb7a40360327c48)) -## [1.0.0](https://github.com/quipucords/quipucords-ui/compare/184defce82aa3d6b0cb5542ed34e81c581edef71...26b6eb0629537148fe57ffa468b412df3369aa0e) (2022-10-26) +- **createCredentialDialog** locale strings ([#185](https://github.com/quipucords/quipucords-ui/pull/185)) ([8490199](https://github.com/quipucords/quipucords-ui/commit/8490199f95798ea7d30e63b1fc83ff4cc688ef56)) +- **scanJobsList** minor test correction ([#184](https://github.com/quipucords/quipucords-ui/pull/184)) ([6adf7e3](https://github.com/quipucords/quipucords-ui/commit/6adf7e3e313ba40722f9bbc6aeb7a40360327c48)) + +## [1.0.0](https://github.com/quipucords/quipucords-ui/compare/184defce82aa3d6b0cb5542ed34e81c581edef71...26b6eb0629537148fe57ffa468b412df3369aa0e) (2022-10-26) ### Performance Improvements -* **toastNotificationsList** toasts to hooks ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([4dc3331](https://github.com/quipucords/quipucords-ui/commit/4dc33310450c9ad1867873ed98a3caad776c3d0c)) -* **app** app base to hooks ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([eef93d9](https://github.com/quipucords/quipucords-ui/commit/eef93d90604c95b6452e8619638a9e7ba682d426)) + +- **toastNotificationsList** toasts to hooks ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([4dc3331](https://github.com/quipucords/quipucords-ui/commit/4dc33310450c9ad1867873ed98a3caad776c3d0c)) +- **app** app base to hooks ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([eef93d9](https://github.com/quipucords/quipucords-ui/commit/eef93d90604c95b6452e8619638a9e7ba682d426)) ### Features -* **viewContext** discovery-151 context for views ([#173](https://github.com/quipucords/quipucords-ui/pull/173)) ([55a9e58](https://github.com/quipucords/quipucords-ui/commit/55a9e58bec53fe239c4cfe54108965e90ac15612)) + +- **viewContext** discovery-151 context for views ([#173](https://github.com/quipucords/quipucords-ui/pull/173)) ([55a9e58](https://github.com/quipucords/quipucords-ui/commit/55a9e58bec53fe239c4cfe54108965e90ac15612)) ### Code Refactoring -* **scanDownload** class to function, hooks ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([da5a8c4](https://github.com/quipucords/quipucords-ui/commit/da5a8c490a511c5f1b0c4a3affee56e7604e8faa)) -* **locale** component strings ([#179](https://github.com/quipucords/quipucords-ui/pull/179)) ([5c22489](https://github.com/quipucords/quipucords-ui/commit/5c224892980329654a36c04db8505ef9fcc7f8c5)) -* **addSourceWizard,createScanDialog** discovery-153 forms ([#174](https://github.com/quipucords/quipucords-ui/pull/174)) ([0f7e9f7](https://github.com/quipucords/quipucords-ui/commit/0f7e9f7934b3a0b7d17c10a47d012d08d93b23dc)) -* **scanJobsList,sourceList** discovery-154, pf4 table ([#174](https://github.com/quipucords/quipucords-ui/pull/174)) ([220857c](https://github.com/quipucords/quipucords-ui/commit/220857c23c5a5d58816b1518a81aaa0ff8f2d88c)) -* **addSourceWizard,createScanDialog** locale strings ([#162](https://github.com/quipucords/quipucords-ui/pull/162)) ([586967a](https://github.com/quipucords/quipucords-ui/commit/586967ab84aa2df2aeec800f993278de189ac388)) -* **viewToolbar** discovery-151 pf4 toolbar ([#172](https://github.com/quipucords/quipucords-ui/pull/172)) ([c2db2ff](https://github.com/quipucords/quipucords-ui/commit/c2db2ff0b644410aa202c8142fb85d1b0780042c)) -* **createCredentialDialog** discovery-153 pf4 textInput ([#161](https://github.com/quipucords/quipucords-ui/pull/161)) ([ce1868a](https://github.com/quipucords/quipucords-ui/commit/ce1868ab19c73a7ece67356a037ddea16235b86c)) -* **addSourceWizardStepTwo** discovery-153 pf4 textInput ([#159](https://github.com/quipucords/quipucords-ui/pull/159)) ([d1192c4](https://github.com/quipucords/quipucords-ui/commit/d1192c43857578b781105cc17a8458ae4c9b5b0d)) -* **textArea** discovery-153 pf4 textArea ([#158](https://github.com/quipucords/quipucords-ui/pull/158)) ([3358126](https://github.com/quipucords/quipucords-ui/commit/33581267f230ebc0ac2f840f468862ffb67fae9f)) -* **checkbox** discovery-153 pf4 checkbox ([#155](https://github.com/quipucords/quipucords-ui/pull/155)) ([dd55ac0](https://github.com/quipucords/quipucords-ui/commit/dd55ac09b95be47d720dbcc2b95c8a37537fb88e)) -* **radio** discovery-153 pf4 radio ([#153](https://github.com/quipucords/quipucords-ui/pull/153)) ([4c99c05](https://github.com/quipucords/quipucords-ui/commit/4c99c05416e08521b3242563ca198884ebb27b4d)) -* **formGroup** discovery-153 pf4 formGroup ([#150](https://github.com/quipucords/quipucords-ui/pull/150)) ([5f5c4f6](https://github.com/quipucords/quipucords-ui/commit/5f5c4f6d022cbcfbabd159d48e33ccf231150c09)) -* **touchspin** discovery-153 pf4 textInput ([#147](https://github.com/quipucords/quipucords-ui/pull/147)) ([1be4616](https://github.com/quipucords/quipucords-ui/commit/1be461692e694812728f8da41c000e106b4a4efd)) + +- **scanDownload** class to function, hooks ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([da5a8c4](https://github.com/quipucords/quipucords-ui/commit/da5a8c490a511c5f1b0c4a3affee56e7604e8faa)) +- **locale** component strings ([#179](https://github.com/quipucords/quipucords-ui/pull/179)) ([5c22489](https://github.com/quipucords/quipucords-ui/commit/5c224892980329654a36c04db8505ef9fcc7f8c5)) +- **addSourceWizard,createScanDialog** discovery-153 forms ([#174](https://github.com/quipucords/quipucords-ui/pull/174)) ([0f7e9f7](https://github.com/quipucords/quipucords-ui/commit/0f7e9f7934b3a0b7d17c10a47d012d08d93b23dc)) +- **scanJobsList,sourceList** discovery-154, pf4 table ([#174](https://github.com/quipucords/quipucords-ui/pull/174)) ([220857c](https://github.com/quipucords/quipucords-ui/commit/220857c23c5a5d58816b1518a81aaa0ff8f2d88c)) +- **addSourceWizard,createScanDialog** locale strings ([#162](https://github.com/quipucords/quipucords-ui/pull/162)) ([586967a](https://github.com/quipucords/quipucords-ui/commit/586967ab84aa2df2aeec800f993278de189ac388)) +- **viewToolbar** discovery-151 pf4 toolbar ([#172](https://github.com/quipucords/quipucords-ui/pull/172)) ([c2db2ff](https://github.com/quipucords/quipucords-ui/commit/c2db2ff0b644410aa202c8142fb85d1b0780042c)) +- **createCredentialDialog** discovery-153 pf4 textInput ([#161](https://github.com/quipucords/quipucords-ui/pull/161)) ([ce1868a](https://github.com/quipucords/quipucords-ui/commit/ce1868ab19c73a7ece67356a037ddea16235b86c)) +- **addSourceWizardStepTwo** discovery-153 pf4 textInput ([#159](https://github.com/quipucords/quipucords-ui/pull/159)) ([d1192c4](https://github.com/quipucords/quipucords-ui/commit/d1192c43857578b781105cc17a8458ae4c9b5b0d)) +- **textArea** discovery-153 pf4 textArea ([#158](https://github.com/quipucords/quipucords-ui/pull/158)) ([3358126](https://github.com/quipucords/quipucords-ui/commit/33581267f230ebc0ac2f840f468862ffb67fae9f)) +- **checkbox** discovery-153 pf4 checkbox ([#155](https://github.com/quipucords/quipucords-ui/pull/155)) ([dd55ac0](https://github.com/quipucords/quipucords-ui/commit/dd55ac09b95be47d720dbcc2b95c8a37537fb88e)) +- **radio** discovery-153 pf4 radio ([#153](https://github.com/quipucords/quipucords-ui/pull/153)) ([4c99c05](https://github.com/quipucords/quipucords-ui/commit/4c99c05416e08521b3242563ca198884ebb27b4d)) +- **formGroup** discovery-153 pf4 formGroup ([#150](https://github.com/quipucords/quipucords-ui/pull/150)) ([5f5c4f6](https://github.com/quipucords/quipucords-ui/commit/5f5c4f6d022cbcfbabd159d48e33ccf231150c09)) +- **touchspin** discovery-153 pf4 textInput ([#147](https://github.com/quipucords/quipucords-ui/pull/147)) ([1be4616](https://github.com/quipucords/quipucords-ui/commit/1be461692e694812728f8da41c000e106b4a4efd)) ### Chores -* **build** discovery-159 generated changelog ([#181](https://github.com/quipucords/quipucords-ui/pull/181)) ([73939d8](https://github.com/quipucords/quipucords-ui/commit/73939d895cd7ed26f63a10e89650505c907d914d)) -* **deps** bump codecov/codecov-action from 3.1.0 to 3.1.1 ([#176](https://github.com/quipucords/quipucords-ui/pull/176)) ([255bc01](https://github.com/quipucords/quipucords-ui/commit/255bc019d83f11c4a9149c01001b191b13b2e86d)) -* **poll,sourceConstants** clean up unused files ([#174](https://github.com/quipucords/quipucords-ui/pull/174)) ([48c201d](https://github.com/quipucords/quipucords-ui/commit/48c201dbf6e6bf8f44050c739fc6d90e96ac07ce)) -* **deps** bump classnames from 2.3.1 to 2.3.2 ([#175](https://github.com/quipucords/quipucords-ui/pull/175)) ([d6453af](https://github.com/quipucords/quipucords-ui/commit/d6453af1f19eb3b99b9375e6b9eba9e49625fa8b)) + +- **build** discovery-159 generated changelog ([#181](https://github.com/quipucords/quipucords-ui/pull/181)) ([73939d8](https://github.com/quipucords/quipucords-ui/commit/73939d895cd7ed26f63a10e89650505c907d914d)) +- **deps** bump codecov/codecov-action from 3.1.0 to 3.1.1 ([#176](https://github.com/quipucords/quipucords-ui/pull/176)) ([255bc01](https://github.com/quipucords/quipucords-ui/commit/255bc019d83f11c4a9149c01001b191b13b2e86d)) +- **poll,sourceConstants** clean up unused files ([#174](https://github.com/quipucords/quipucords-ui/pull/174)) ([48c201d](https://github.com/quipucords/quipucords-ui/commit/48c201dbf6e6bf8f44050c739fc6d90e96ac07ce)) +- **deps** bump classnames from 2.3.1 to 2.3.2 ([#175](https://github.com/quipucords/quipucords-ui/pull/175)) ([d6453af](https://github.com/quipucords/quipucords-ui/commit/d6453af1f19eb3b99b9375e6b9eba9e49625fa8b)) ### Bug Fixes -* **build** discovery-198 replace assets paths ([#182](https://github.com/quipucords/quipucords-ui/pull/182)) ([26b6eb0](https://github.com/quipucords/quipucords-ui/commit/26b6eb0629537148fe57ffa468b412df3369aa0e)) -* **credentialsTableCells** discovery-197 auth type string ([#183](https://github.com/quipucords/quipucords-ui/pull/183)) ([68ea5d9](https://github.com/quipucords/quipucords-ui/commit/68ea5d9e4e5907ce35c87254ca315bccc1dfd2ae)) -* **credentials,scans,sources** center pending modal ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([94739bc](https://github.com/quipucords/quipucords-ui/commit/94739bccb499701353bdb0b7678573e8867f14f3)) -* **credentialsContext,sourcesContext** delete messaging ([#177](https://github.com/quipucords/quipucords-ui/pull/177)) ([5bbc734](https://github.com/quipucords/quipucords-ui/commit/5bbc734efce7f36382c30a7669120703966df8ed)) -* **credentialsTableCells** discovery-154 sources icon ([#177](https://github.com/quipucords/quipucords-ui/pull/177)) ([0f650d5](https://github.com/quipucords/quipucords-ui/commit/0f650d5adb402dfbefc8c7069f9194a47dd626d4)) -* **formGroup** discovery-153 use validatedOptions ([#161](https://github.com/quipucords/quipucords-ui/pull/161)) ([68e89a8](https://github.com/quipucords/quipucords-ui/commit/68e89a89a870a1c6f9a99e59e70397ee138550c3)) -* **textInput** discovery-151 state, callback sequence ([#159](https://github.com/quipucords/quipucords-ui/pull/159)) ([4e2012a](https://github.com/quipucords/quipucords-ui/commit/4e2012a48dfb64b66de9db9bc3347542184fc5a3)) -* **addSourceWizardStepTwo** invalid step check ([#158](https://github.com/quipucords/quipucords-ui/pull/158)) ([1906783](https://github.com/quipucords/quipucords-ui/commit/190678345662fc8c71f13f6f162647843cdcf172)) -* **touchspin** discovery-153 revert state value ([#150](https://github.com/quipucords/quipucords-ui/pull/150)) ([dcd8c0b](https://github.com/quipucords/quipucords-ui/commit/dcd8c0b4b765f402a0c8d845e364963c8375b853)) - -## 0.11.1 (2022-09-22) + +- **build** discovery-198 replace assets paths ([#182](https://github.com/quipucords/quipucords-ui/pull/182)) ([26b6eb0](https://github.com/quipucords/quipucords-ui/commit/26b6eb0629537148fe57ffa468b412df3369aa0e)) +- **credentialsTableCells** discovery-197 auth type string ([#183](https://github.com/quipucords/quipucords-ui/pull/183)) ([68ea5d9](https://github.com/quipucords/quipucords-ui/commit/68ea5d9e4e5907ce35c87254ca315bccc1dfd2ae)) +- **credentials,scans,sources** center pending modal ([#180](https://github.com/quipucords/quipucords-ui/pull/180)) ([94739bc](https://github.com/quipucords/quipucords-ui/commit/94739bccb499701353bdb0b7678573e8867f14f3)) +- **credentialsContext,sourcesContext** delete messaging ([#177](https://github.com/quipucords/quipucords-ui/pull/177)) ([5bbc734](https://github.com/quipucords/quipucords-ui/commit/5bbc734efce7f36382c30a7669120703966df8ed)) +- **credentialsTableCells** discovery-154 sources icon ([#177](https://github.com/quipucords/quipucords-ui/pull/177)) ([0f650d5](https://github.com/quipucords/quipucords-ui/commit/0f650d5adb402dfbefc8c7069f9194a47dd626d4)) +- **formGroup** discovery-153 use validatedOptions ([#161](https://github.com/quipucords/quipucords-ui/pull/161)) ([68e89a8](https://github.com/quipucords/quipucords-ui/commit/68e89a89a870a1c6f9a99e59e70397ee138550c3)) +- **textInput** discovery-151 state, callback sequence ([#159](https://github.com/quipucords/quipucords-ui/pull/159)) ([4e2012a](https://github.com/quipucords/quipucords-ui/commit/4e2012a48dfb64b66de9db9bc3347542184fc5a3)) +- **addSourceWizardStepTwo** invalid step check ([#158](https://github.com/quipucords/quipucords-ui/pull/158)) ([1906783](https://github.com/quipucords/quipucords-ui/commit/190678345662fc8c71f13f6f162647843cdcf172)) +- **touchspin** discovery-153 revert state value ([#150](https://github.com/quipucords/quipucords-ui/pull/150)) ([dcd8c0b](https://github.com/quipucords/quipucords-ui/commit/dcd8c0b4b765f402a0c8d845e364963c8375b853)) + +## 0.11.1 (2022-09-22) ### Bug Fixes -* **build** discovery-174 css font paths ([#170](https://github.com/quipucords/quipucords-ui/pull/170)) ([d616dfb](https://github.com/quipucords/quipucords-ui/commit/d616dfbb30a7ccc71ff822569c58bf443c51eda8)) + +- **build** discovery-174 css font paths ([#170](https://github.com/quipucords/quipucords-ui/pull/170)) ([d616dfb](https://github.com/quipucords/quipucords-ui/commit/d616dfbb30a7ccc71ff822569c58bf443c51eda8)) ## 0.11.0 (2022-09-21) ### Features -* **pf4-style** discovery-8 pf4 base css, scss ([#86](https://github.com/quipucords/quipucords-ui/pull/86)) ([e17a5ea](https://github.com/quipucords/quipucords-ui/commit/e17a5eaa13745c91a8c13936074e568716b941d0)) -* **modal** discovery-148 pf4 modal wrapper ([#110](https://github.com/quipucords/quipucords-ui/pull/110)) ([8bc5c28](https://github.com/quipucords/quipucords-ui/commit/8bc5c282cebf114db01ce7fa62d128cd164e3ca5)) -* **wizard** discovery-153 pf4 wizard wrapper ([#124](https://github.com/quipucords/quipucords-ui/pull/124)) ([d9cd662](https://github.com/quipucords/quipucords-ui/commit/d9cd662707f09eccac5b01cb44e8fc4a091f8405)) -* **addCredentialType** discovery-152 button selector ([#130](https://github.com/quipucords/quipucords-ui/pull/130)) ([4d9d524](https://github.com/quipucords/quipucords-ui/commit/4d9d524ba2a63b86c9d27cbe80d24ddca93b2f05)) -* **table** discovery-154 pf4 table wrapper ([#139](https://github.com/quipucords/quipucords-ui/pull/139)) ([1c0b4c8](https://github.com/quipucords/quipucords-ui/commit/1c0b4c82a3f1faa76e5a2bd36800d43f7f626ddb)) -* **useTimeout** discovery-154 setTimeout hook ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([2af7126](https://github.com/quipucords/quipucords-ui/commit/2af7126978648a087abc2d25324237235e7e5a85)) -* **contextIcon** discovery-154 programmatic icons ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([6632ca9](https://github.com/quipucords/quipucords-ui/commit/6632ca9c392efb9b187f6efb962f07dbe777b5b2)) -* **textInput,formHelpers** discovery-151 pf4 textInput ([#149](https://github.com/quipucords/quipucords-ui/pull/149)) ([5ecf626](https://github.com/quipucords/quipucords-ui/commit/5ecf626cbec18ffea4a9416dd36dd355f594c5f2)) -* **contextIconAction** discovery-154 action icons ([#152](https://github.com/quipucords/quipucords-ui/pull/152)) ([0fe3186](https://github.com/quipucords/quipucords-ui/commit/0fe31860cb1a28154c8b987ec797743f2d57d19e)) -* **routerContext** discovery-150 hook context ([#169](https://github.com/quipucords/quipucords-ui/pull/169)) ([aceed19](https://github.com/quipucords/quipucords-ui/commit/aceed191007ea71bae8296a869682365ce220db3)) + +- **pf4-style** discovery-8 pf4 base css, scss ([#86](https://github.com/quipucords/quipucords-ui/pull/86)) ([e17a5ea](https://github.com/quipucords/quipucords-ui/commit/e17a5eaa13745c91a8c13936074e568716b941d0)) +- **modal** discovery-148 pf4 modal wrapper ([#110](https://github.com/quipucords/quipucords-ui/pull/110)) ([8bc5c28](https://github.com/quipucords/quipucords-ui/commit/8bc5c282cebf114db01ce7fa62d128cd164e3ca5)) +- **wizard** discovery-153 pf4 wizard wrapper ([#124](https://github.com/quipucords/quipucords-ui/pull/124)) ([d9cd662](https://github.com/quipucords/quipucords-ui/commit/d9cd662707f09eccac5b01cb44e8fc4a091f8405)) +- **addCredentialType** discovery-152 button selector ([#130](https://github.com/quipucords/quipucords-ui/pull/130)) ([4d9d524](https://github.com/quipucords/quipucords-ui/commit/4d9d524ba2a63b86c9d27cbe80d24ddca93b2f05)) +- **table** discovery-154 pf4 table wrapper ([#139](https://github.com/quipucords/quipucords-ui/pull/139)) ([1c0b4c8](https://github.com/quipucords/quipucords-ui/commit/1c0b4c82a3f1faa76e5a2bd36800d43f7f626ddb)) +- **useTimeout** discovery-154 setTimeout hook ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([2af7126](https://github.com/quipucords/quipucords-ui/commit/2af7126978648a087abc2d25324237235e7e5a85)) +- **contextIcon** discovery-154 programmatic icons ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([6632ca9](https://github.com/quipucords/quipucords-ui/commit/6632ca9c392efb9b187f6efb962f07dbe777b5b2)) +- **textInput,formHelpers** discovery-151 pf4 textInput ([#149](https://github.com/quipucords/quipucords-ui/pull/149)) ([5ecf626](https://github.com/quipucords/quipucords-ui/commit/5ecf626cbec18ffea4a9416dd36dd355f594c5f2)) +- **contextIconAction** discovery-154 action icons ([#152](https://github.com/quipucords/quipucords-ui/pull/152)) ([0fe3186](https://github.com/quipucords/quipucords-ui/commit/0fe31860cb1a28154c8b987ec797743f2d57d19e)) +- **routerContext** discovery-150 hook context ([#169](https://github.com/quipucords/quipucords-ui/pull/169)) ([aceed19](https://github.com/quipucords/quipucords-ui/commit/aceed191007ea71bae8296a869682365ce220db3)) ### Bug Fixes -* **build** allow running review, stage parallel ([#86](https://github.com/quipucords/quipucords-ui/pull/86)) ([98885cc](https://github.com/quipucords/quipucords-ui/commit/98885cc68854cc4d52a0f9a373656d27c434f286)) -* **style** discovery-8 css, scss vars for color ([#86](https://github.com/quipucords/quipucords-ui/pull/86)) ([9abe42a](https://github.com/quipucords/quipucords-ui/commit/9abe42a465696bb5d0198dfc32b8c65e950072db)) -* **build** discovery-174 adjust templates css ([#157](https://github.com/quipucords/quipucords-ui/pull/157)) ([78b4aa8](https://github.com/quipucords/quipucords-ui/commit/78b4aa801a59c1e6010f700bcea3be47306ba750)) -* **testing** use i18n unit, remove integration check ([#87](https://github.com/quipucords/quipucords-ui/pull/87)) ([a0797c6](https://github.com/quipucords/quipucords-ui/commit/a0797c6399df25708cb45cf7cbda45103b172818)) -* **helpers** discovery-8 consistent brand, getCurrentDate ([#87](https://github.com/quipucords/quipucords-ui/pull/87)) ([57d5f80](https://github.com/quipucords/quipucords-ui/commit/57d5f8063b02ad2128586bfe6497d25c9ab571ae)) -* **pf4-style** expose scss variables ([#110](https://github.com/quipucords/quipucords-ui/pull/110)) ([a62c2be](https://github.com/quipucords/quipucords-ui/commit/a62c2be7eab3ad77c29f4dd4ca5e754739b412d0)) -* **confirmationModal** expand behavior, allow children ([#113](https://github.com/quipucords/quipucords-ui/pull/113)) ([47975db](https://github.com/quipucords/quipucords-ui/commit/47975db51a869be3e44cdf23e4e438dfaf860345)) -* **testing** expand toastNotificationsList snapshots ([#115](https://github.com/quipucords/quipucords-ui/pull/115)) ([fdb48fb](https://github.com/quipucords/quipucords-ui/commit/fdb48fbb1bc7674512d0794d5cda2f344a66c3b3)) -* **i18n** discovery-8 partial context into keys ([#124](https://github.com/quipucords/quipucords-ui/pull/124)) ([d241b43](https://github.com/quipucords/quipucords-ui/commit/d241b43c1e7676c2e72ec359d6115808c97d8056)) -* **table** discovery-154 key generation ([#140](https://github.com/quipucords/quipucords-ui/pull/140)) ([b917eb0](https://github.com/quipucords/quipucords-ui/commit/b917eb01e827d4b36919c5d95ef3e9609deba8c7)) -* **dropdownSelect** discovery-152 props, placeholder ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([4f7c6d9](https://github.com/quipucords/quipucords-ui/commit/4f7c6d91ca0e82864c9657e661732c7b08899039)) -* **tooltip** discovery-148 hover content wrapper ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([95371e5](https://github.com/quipucords/quipucords-ui/commit/95371e53c910653e0bae4d77cd3d468e2a7c748b)) -* **table** discovery-154 pass data, keys, styling ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([be6a8fd](https://github.com/quipucords/quipucords-ui/commit/be6a8fdd86e22e132f452b061e426b30824a53a5)) -* **helpers** discovery-154 global poll interval ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([afaa610](https://github.com/quipucords/quipucords-ui/commit/afaa6104b4025ac62011673ee6cfb38b76f78dbb)) -* **testing** mock react-redux ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([dba7598](https://github.com/quipucords/quipucords-ui/commit/dba7598bd14ef42e97f0d13473137230938d5a8e)) -* **dropdownSelect** discovery-151 undefined options ([#149](https://github.com/quipucords/quipucords-ui/pull/149)) ([77052a5](https://github.com/quipucords/quipucords-ui/commit/77052a574defd9ad7d62effa8a15fbef6886e257)) -* **scansTableCells,context** discovery-154 actions ([#152](https://github.com/quipucords/quipucords-ui/pull/152)) ([5334351](https://github.com/quipucords/quipucords-ui/commit/53343513df1b90f01325c400e83f91fb723055b9)) -* **poll,scanDownload** propTypes, node instead of string ([#154](https://github.com/quipucords/quipucords-ui/pull/154)) ([ad5bd48](https://github.com/quipucords/quipucords-ui/commit/ad5bd486e85ab828683e7764f6df19b9004d1e29)) -* **tableHelpers** discovery-154 expand width percentages ([#160](https://github.com/quipucords/quipucords-ui/pull/160)) ([e8fc2d8](https://github.com/quipucords/quipucords-ui/commit/e8fc2d8b286ad255e535a8876a9928c75fa74848)) -* **sourcesContext** discovery-154 delete source ([#163](https://github.com/quipucords/quipucords-ui/pull/163)) ([5039b2d](https://github.com/quipucords/quipucords-ui/commit/5039b2d9b1ba4a8424a59bf2fc7863da182267f6)) -* **credentials,scans,sources** discovery-154 apiTypes ([#163](https://github.com/quipucords/quipucords-ui/pull/163)) ([68df0b7](https://github.com/quipucords/quipucords-ui/commit/68df0b76626b9123377fcbe164bccdf23153c55f)) -* **sources** discovery-154 scans button ([#166](https://github.com/quipucords/quipucords-ui/pull/166)) ([cc7da38](https://github.com/quipucords/quipucords-ui/commit/cc7da38e873100d90b15ec0178f140337efdb29e)) -* **toastNotificationsList** discovery-148 pf4 alertVariant ([#167](https://github.com/quipucords/quipucords-ui/pull/167)) ([d37cf83](https://github.com/quipucords/quipucords-ui/commit/d37cf837e2380338f105faec367d4920540d2fbf)) -* **scansEmptyState** discovery-154 detect sources ([#169](https://github.com/quipucords/quipucords-ui/pull/169)) ([9b98de6](https://github.com/quipucords/quipucords-ui/commit/9b98de69c31be9c9cf7d52ff4121b7295e4c9aa7)) + +- **build** allow running review, stage parallel ([#86](https://github.com/quipucords/quipucords-ui/pull/86)) ([98885cc](https://github.com/quipucords/quipucords-ui/commit/98885cc68854cc4d52a0f9a373656d27c434f286)) +- **style** discovery-8 css, scss vars for color ([#86](https://github.com/quipucords/quipucords-ui/pull/86)) ([9abe42a](https://github.com/quipucords/quipucords-ui/commit/9abe42a465696bb5d0198dfc32b8c65e950072db)) +- **build** discovery-174 adjust templates css ([#157](https://github.com/quipucords/quipucords-ui/pull/157)) ([78b4aa8](https://github.com/quipucords/quipucords-ui/commit/78b4aa801a59c1e6010f700bcea3be47306ba750)) +- **testing** use i18n unit, remove integration check ([#87](https://github.com/quipucords/quipucords-ui/pull/87)) ([a0797c6](https://github.com/quipucords/quipucords-ui/commit/a0797c6399df25708cb45cf7cbda45103b172818)) +- **helpers** discovery-8 consistent brand, getCurrentDate ([#87](https://github.com/quipucords/quipucords-ui/pull/87)) ([57d5f80](https://github.com/quipucords/quipucords-ui/commit/57d5f8063b02ad2128586bfe6497d25c9ab571ae)) +- **pf4-style** expose scss variables ([#110](https://github.com/quipucords/quipucords-ui/pull/110)) ([a62c2be](https://github.com/quipucords/quipucords-ui/commit/a62c2be7eab3ad77c29f4dd4ca5e754739b412d0)) +- **confirmationModal** expand behavior, allow children ([#113](https://github.com/quipucords/quipucords-ui/pull/113)) ([47975db](https://github.com/quipucords/quipucords-ui/commit/47975db51a869be3e44cdf23e4e438dfaf860345)) +- **testing** expand toastNotificationsList snapshots ([#115](https://github.com/quipucords/quipucords-ui/pull/115)) ([fdb48fb](https://github.com/quipucords/quipucords-ui/commit/fdb48fbb1bc7674512d0794d5cda2f344a66c3b3)) +- **i18n** discovery-8 partial context into keys ([#124](https://github.com/quipucords/quipucords-ui/pull/124)) ([d241b43](https://github.com/quipucords/quipucords-ui/commit/d241b43c1e7676c2e72ec359d6115808c97d8056)) +- **table** discovery-154 key generation ([#140](https://github.com/quipucords/quipucords-ui/pull/140)) ([b917eb0](https://github.com/quipucords/quipucords-ui/commit/b917eb01e827d4b36919c5d95ef3e9609deba8c7)) +- **dropdownSelect** discovery-152 props, placeholder ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([4f7c6d9](https://github.com/quipucords/quipucords-ui/commit/4f7c6d91ca0e82864c9657e661732c7b08899039)) +- **tooltip** discovery-148 hover content wrapper ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([95371e5](https://github.com/quipucords/quipucords-ui/commit/95371e53c910653e0bae4d77cd3d468e2a7c748b)) +- **table** discovery-154 pass data, keys, styling ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([be6a8fd](https://github.com/quipucords/quipucords-ui/commit/be6a8fdd86e22e132f452b061e426b30824a53a5)) +- **helpers** discovery-154 global poll interval ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([afaa610](https://github.com/quipucords/quipucords-ui/commit/afaa6104b4025ac62011673ee6cfb38b76f78dbb)) +- **testing** mock react-redux ([#145](https://github.com/quipucords/quipucords-ui/pull/145)) ([dba7598](https://github.com/quipucords/quipucords-ui/commit/dba7598bd14ef42e97f0d13473137230938d5a8e)) +- **dropdownSelect** discovery-151 undefined options ([#149](https://github.com/quipucords/quipucords-ui/pull/149)) ([77052a5](https://github.com/quipucords/quipucords-ui/commit/77052a574defd9ad7d62effa8a15fbef6886e257)) +- **scansTableCells,context** discovery-154 actions ([#152](https://github.com/quipucords/quipucords-ui/pull/152)) ([5334351](https://github.com/quipucords/quipucords-ui/commit/53343513df1b90f01325c400e83f91fb723055b9)) +- **poll,scanDownload** propTypes, node instead of string ([#154](https://github.com/quipucords/quipucords-ui/pull/154)) ([ad5bd48](https://github.com/quipucords/quipucords-ui/commit/ad5bd486e85ab828683e7764f6df19b9004d1e29)) +- **tableHelpers** discovery-154 expand width percentages ([#160](https://github.com/quipucords/quipucords-ui/pull/160)) ([e8fc2d8](https://github.com/quipucords/quipucords-ui/commit/e8fc2d8b286ad255e535a8876a9928c75fa74848)) +- **sourcesContext** discovery-154 delete source ([#163](https://github.com/quipucords/quipucords-ui/pull/163)) ([5039b2d](https://github.com/quipucords/quipucords-ui/commit/5039b2d9b1ba4a8424a59bf2fc7863da182267f6)) +- **credentials,scans,sources** discovery-154 apiTypes ([#163](https://github.com/quipucords/quipucords-ui/pull/163)) ([68df0b7](https://github.com/quipucords/quipucords-ui/commit/68df0b76626b9123377fcbe164bccdf23153c55f)) +- **sources** discovery-154 scans button ([#166](https://github.com/quipucords/quipucords-ui/pull/166)) ([cc7da38](https://github.com/quipucords/quipucords-ui/commit/cc7da38e873100d90b15ec0178f140337efdb29e)) +- **toastNotificationsList** discovery-148 pf4 alertVariant ([#167](https://github.com/quipucords/quipucords-ui/pull/167)) ([d37cf83](https://github.com/quipucords/quipucords-ui/commit/d37cf837e2380338f105faec367d4920540d2fbf)) +- **scansEmptyState** discovery-154 detect sources ([#169](https://github.com/quipucords/quipucords-ui/pull/169)) ([9b98de6](https://github.com/quipucords/quipucords-ui/commit/9b98de69c31be9c9cf7d52ff4121b7295e4c9aa7)) ### Code Refactoring -* **aboutModal** discovery-148 pf4 conversion ([#87](https://github.com/quipucords/quipucords-ui/pull/87)) ([7caa845](https://github.com/quipucords/quipucords-ui/commit/7caa8451ddee5075873fab466974fc46784d5200)) -* **modal** discovery-148 pf4 modal wrapper ([#88](https://github.com/quipucords/quipucords-ui/pull/88)) ([b843c7e](https://github.com/quipucords/quipucords-ui/commit/b843c7e6fbd0a8d027655a29c37e3f7eca62b36f)) -* **createCredentialDialog** discovery-148 pf4 alert ([#108](https://github.com/quipucords/quipucords-ui/pull/108)) ([1aa7482](https://github.com/quipucords/quipucords-ui/commit/1aa7482789eabe4714aedfcca897f004ae7d1ac6)) -* **authentication** discovery-148 pf4 alert, locale ([#112](https://github.com/quipucords/quipucords-ui/pull/112)) ([2cd5ae2](https://github.com/quipucords/quipucords-ui/commit/2cd5ae29edcb599398a67582dccd1c28e0ee5d5f)) -* **authentication** discovery-148 replace empty-state ([#113](https://github.com/quipucords/quipucords-ui/pull/113)) ([ce28975](https://github.com/quipucords/quipucords-ui/commit/ce2897561367c5ef1489c0bf5362f20e2c64a6cb)) -* **credentials** discovery-148 pf4 empty-state ([#116](https://github.com/quipucords/quipucords-ui/pull/116)) ([e2a17f2](https://github.com/quipucords/quipucords-ui/commit/e2a17f2a8f1263fd4e63b1ae62f5c8e27ad08996)) -* **refreshTimeButton** discovery-149 pf4 button, icon ([#114](https://github.com/quipucords/quipucords-ui/pull/114)) ([911b408](https://github.com/quipucords/quipucords-ui/commit/911b408ea8b4fb128b4f91176df056424f80c710)) -* **scans** discovery-148 pf4 empty-state ([#117](https://github.com/quipucords/quipucords-ui/pull/117)) ([10883ca](https://github.com/quipucords/quipucords-ui/commit/10883ca816279039ac826173da17f04fc836881b)) -* **toastNotificationsList** discovery-148, pf4 alert ([#115](https://github.com/quipucords/quipucords-ui/pull/115)) ([64bd7e4](https://github.com/quipucords/quipucords-ui/commit/64bd7e401ff76608640c0df553cde7bb2927dc8e)) -* **sources** discovery-148 pf4 empty-state ([#120](https://github.com/quipucords/quipucords-ui/pull/120)) ([113da41](https://github.com/quipucords/quipucords-ui/commit/113da41a2b791dc3597ee47105eeb0309ff68583)) -* **creds,sources,scans** discovery-149 emptyState grid ([#121](https://github.com/quipucords/quipucords-ui/pull/121)) ([2cc6f5d](https://github.com/quipucords/quipucords-ui/commit/2cc6f5d33da04475d51005b30d98d00cb76f9c45)) -* **addSourceWizard** discovery-153, pf4 wizard ([#124](https://github.com/quipucords/quipucords-ui/pull/124)) ([0aed24d](https://github.com/quipucords/quipucords-ui/commit/0aed24dd273f1e200c6ecec870d0df4db71fae02)) -* **scanHostList** discovery-148, pf4 empty-state ([#125](https://github.com/quipucords/quipucords-ui/pull/125)) ([832761b](https://github.com/quipucords/quipucords-ui/commit/832761b9c7678cc4255138b2f62a9a97d85f213c)) -* **creds,sources,scans** discovery-149 pf4 grid, list ([#126](https://github.com/quipucords/quipucords-ui/pull/126)) ([2a8789b](https://github.com/quipucords/quipucords-ui/commit/2a8789b3cba4c055d6e7058ca563a397087cd7ef)) -* **dropdownSelect** discovery-152 pf4 select, dropdown ([#127](https://github.com/quipucords/quipucords-ui/pull/127)) ([9ca4c48](https://github.com/quipucords/quipucords-ui/commit/9ca4c489513173165f819be82376f8e8574eb834)) -* **dropdownSelect** discovery-152 pf4 dropdown ([#130](https://github.com/quipucords/quipucords-ui/pull/130)) ([3745d5e](https://github.com/quipucords/quipucords-ui/commit/3745d5e0a463804c2c75303bccc9d3cffaeb4150)) -* **credentials** discovery-152, pf4 dropdown ([#130](https://github.com/quipucords/quipucords-ui/pull/130)) ([0416840](https://github.com/quipucords/quipucords-ui/commit/0416840887815fa82cc9a5c7182d24e66345390f)) -* **tooltip** discovery-148 pf4 tooltip, popover ([#132](https://github.com/quipucords/quipucords-ui/pull/132)) ([f8a0544](https://github.com/quipucords/quipucords-ui/commit/f8a05449d6c118b560788187e4fedbcc5c0444de)) -* **pagination** discovery 154 pf4 pagination ([#129](https://github.com/quipucords/quipucords-ui/pull/129)) ([292d158](https://github.com/quipucords/quipucords-ui/commit/292d1580644667a5686cb6e5c0f1e0d4a2f8cbc1)) -* **buttons** discovery-149 sources pf4 buttons ([#136](https://github.com/quipucords/quipucords-ui/pull/136)) ([57ca4f5](https://github.com/quipucords/quipucords-ui/commit/57ca4f51500e2e287518f92c79331caff2bb4793)) -* **buttons** discovery-149 scans,credentials pf buttons ([#142](https://github.com/quipucords/quipucords-ui/pull/142)) ([637464c](https://github.com/quipucords/quipucords-ui/commit/637464c018a716f1a5bb2976763b7d415ae59add)) -* **createScanDialog** discovery-148, pf4 alert ([#144](https://github.com/quipucords/quipucords-ui/pull/144)) ([c1e2ace](https://github.com/quipucords/quipucords-ui/commit/c1e2aceac2ecfd3bfc3e1694cb72264580f4033a)) -* **sources** discovery-154, pf4 table ([#141](https://github.com/quipucords/quipucords-ui/pull/141)) ([1e8ccb7](https://github.com/quipucords/quipucords-ui/commit/1e8ccb7f8b4b9631128fa761baf9a94efa52696f)) -* **scans** discovery-154, pf4 table ([#152](https://github.com/quipucords/quipucords-ui/pull/152)) ([593ffb3](https://github.com/quipucords/quipucords-ui/commit/593ffb308a48c2691a60d70038231cb036b08b53)) -* **credentials** discovery-154, pf4 table ([#160](https://github.com/quipucords/quipucords-ui/pull/160)) ([8a716ee](https://github.com/quipucords/quipucords-ui/commit/8a716eee76144a8dfc85ac916901f8e0b626bf19)) -* **helpers,redux** discovery-154, clean up ([#163](https://github.com/quipucords/quipucords-ui/pull/163)) ([967c5be](https://github.com/quipucords/quipucords-ui/commit/967c5bebb61804429f43978d685f9ca57198c5a8)) -* **router** discovery-150 router npm update ([#164](https://github.com/quipucords/quipucords-ui/pull/164)) ([18ad1cf](https://github.com/quipucords/quipucords-ui/commit/18ad1cf3d28b0f8cb24c86f528de4789c2b48287)) -* **button,icon,spinner** discovery-149 pf4 replacements ([#165](https://github.com/quipucords/quipucords-ui/pull/165)) ([21846cc](https://github.com/quipucords/quipucords-ui/commit/21846cc4454b0fa2d1cf0421451dc6a3ec9784ac)) + +- **aboutModal** discovery-148 pf4 conversion ([#87](https://github.com/quipucords/quipucords-ui/pull/87)) ([7caa845](https://github.com/quipucords/quipucords-ui/commit/7caa8451ddee5075873fab466974fc46784d5200)) +- **modal** discovery-148 pf4 modal wrapper ([#88](https://github.com/quipucords/quipucords-ui/pull/88)) ([b843c7e](https://github.com/quipucords/quipucords-ui/commit/b843c7e6fbd0a8d027655a29c37e3f7eca62b36f)) +- **createCredentialDialog** discovery-148 pf4 alert ([#108](https://github.com/quipucords/quipucords-ui/pull/108)) ([1aa7482](https://github.com/quipucords/quipucords-ui/commit/1aa7482789eabe4714aedfcca897f004ae7d1ac6)) +- **authentication** discovery-148 pf4 alert, locale ([#112](https://github.com/quipucords/quipucords-ui/pull/112)) ([2cd5ae2](https://github.com/quipucords/quipucords-ui/commit/2cd5ae29edcb599398a67582dccd1c28e0ee5d5f)) +- **authentication** discovery-148 replace empty-state ([#113](https://github.com/quipucords/quipucords-ui/pull/113)) ([ce28975](https://github.com/quipucords/quipucords-ui/commit/ce2897561367c5ef1489c0bf5362f20e2c64a6cb)) +- **credentials** discovery-148 pf4 empty-state ([#116](https://github.com/quipucords/quipucords-ui/pull/116)) ([e2a17f2](https://github.com/quipucords/quipucords-ui/commit/e2a17f2a8f1263fd4e63b1ae62f5c8e27ad08996)) +- **refreshTimeButton** discovery-149 pf4 button, icon ([#114](https://github.com/quipucords/quipucords-ui/pull/114)) ([911b408](https://github.com/quipucords/quipucords-ui/commit/911b408ea8b4fb128b4f91176df056424f80c710)) +- **scans** discovery-148 pf4 empty-state ([#117](https://github.com/quipucords/quipucords-ui/pull/117)) ([10883ca](https://github.com/quipucords/quipucords-ui/commit/10883ca816279039ac826173da17f04fc836881b)) +- **toastNotificationsList** discovery-148, pf4 alert ([#115](https://github.com/quipucords/quipucords-ui/pull/115)) ([64bd7e4](https://github.com/quipucords/quipucords-ui/commit/64bd7e401ff76608640c0df553cde7bb2927dc8e)) +- **sources** discovery-148 pf4 empty-state ([#120](https://github.com/quipucords/quipucords-ui/pull/120)) ([113da41](https://github.com/quipucords/quipucords-ui/commit/113da41a2b791dc3597ee47105eeb0309ff68583)) +- **creds,sources,scans** discovery-149 emptyState grid ([#121](https://github.com/quipucords/quipucords-ui/pull/121)) ([2cc6f5d](https://github.com/quipucords/quipucords-ui/commit/2cc6f5d33da04475d51005b30d98d00cb76f9c45)) +- **addSourceWizard** discovery-153, pf4 wizard ([#124](https://github.com/quipucords/quipucords-ui/pull/124)) ([0aed24d](https://github.com/quipucords/quipucords-ui/commit/0aed24dd273f1e200c6ecec870d0df4db71fae02)) +- **scanHostList** discovery-148, pf4 empty-state ([#125](https://github.com/quipucords/quipucords-ui/pull/125)) ([832761b](https://github.com/quipucords/quipucords-ui/commit/832761b9c7678cc4255138b2f62a9a97d85f213c)) +- **creds,sources,scans** discovery-149 pf4 grid, list ([#126](https://github.com/quipucords/quipucords-ui/pull/126)) ([2a8789b](https://github.com/quipucords/quipucords-ui/commit/2a8789b3cba4c055d6e7058ca563a397087cd7ef)) +- **dropdownSelect** discovery-152 pf4 select, dropdown ([#127](https://github.com/quipucords/quipucords-ui/pull/127)) ([9ca4c48](https://github.com/quipucords/quipucords-ui/commit/9ca4c489513173165f819be82376f8e8574eb834)) +- **dropdownSelect** discovery-152 pf4 dropdown ([#130](https://github.com/quipucords/quipucords-ui/pull/130)) ([3745d5e](https://github.com/quipucords/quipucords-ui/commit/3745d5e0a463804c2c75303bccc9d3cffaeb4150)) +- **credentials** discovery-152, pf4 dropdown ([#130](https://github.com/quipucords/quipucords-ui/pull/130)) ([0416840](https://github.com/quipucords/quipucords-ui/commit/0416840887815fa82cc9a5c7182d24e66345390f)) +- **tooltip** discovery-148 pf4 tooltip, popover ([#132](https://github.com/quipucords/quipucords-ui/pull/132)) ([f8a0544](https://github.com/quipucords/quipucords-ui/commit/f8a05449d6c118b560788187e4fedbcc5c0444de)) +- **pagination** discovery 154 pf4 pagination ([#129](https://github.com/quipucords/quipucords-ui/pull/129)) ([292d158](https://github.com/quipucords/quipucords-ui/commit/292d1580644667a5686cb6e5c0f1e0d4a2f8cbc1)) +- **buttons** discovery-149 sources pf4 buttons ([#136](https://github.com/quipucords/quipucords-ui/pull/136)) ([57ca4f5](https://github.com/quipucords/quipucords-ui/commit/57ca4f51500e2e287518f92c79331caff2bb4793)) +- **buttons** discovery-149 scans,credentials pf buttons ([#142](https://github.com/quipucords/quipucords-ui/pull/142)) ([637464c](https://github.com/quipucords/quipucords-ui/commit/637464c018a716f1a5bb2976763b7d415ae59add)) +- **createScanDialog** discovery-148, pf4 alert ([#144](https://github.com/quipucords/quipucords-ui/pull/144)) ([c1e2ace](https://github.com/quipucords/quipucords-ui/commit/c1e2aceac2ecfd3bfc3e1694cb72264580f4033a)) +- **sources** discovery-154, pf4 table ([#141](https://github.com/quipucords/quipucords-ui/pull/141)) ([1e8ccb7](https://github.com/quipucords/quipucords-ui/commit/1e8ccb7f8b4b9631128fa761baf9a94efa52696f)) +- **scans** discovery-154, pf4 table ([#152](https://github.com/quipucords/quipucords-ui/pull/152)) ([593ffb3](https://github.com/quipucords/quipucords-ui/commit/593ffb308a48c2691a60d70038231cb036b08b53)) +- **credentials** discovery-154, pf4 table ([#160](https://github.com/quipucords/quipucords-ui/pull/160)) ([8a716ee](https://github.com/quipucords/quipucords-ui/commit/8a716eee76144a8dfc85ac916901f8e0b626bf19)) +- **helpers,redux** discovery-154, clean up ([#163](https://github.com/quipucords/quipucords-ui/pull/163)) ([967c5be](https://github.com/quipucords/quipucords-ui/commit/967c5bebb61804429f43978d685f9ca57198c5a8)) +- **router** discovery-150 router npm update ([#164](https://github.com/quipucords/quipucords-ui/pull/164)) ([18ad1cf](https://github.com/quipucords/quipucords-ui/commit/18ad1cf3d28b0f8cb24c86f528de4789c2b48287)) +- **button,icon,spinner** discovery-149 pf4 replacements ([#165](https://github.com/quipucords/quipucords-ui/pull/165)) ([21846cc](https://github.com/quipucords/quipucords-ui/commit/21846cc4454b0fa2d1cf0421451dc6a3ec9784ac)) ## 0.10.1 (2022-08-17) ### Bug Fixes -* **build:** discovery-174 templates css ([#143](https://github.com/quipucords/quipucords-ui/issues/143)) ([ea98268](https://github.com/quipucords/quipucords-ui/commit/ea982687ad3347cff942782ffc947dd2172ccc1c)) +- **build:** discovery-174 templates css ([#143](https://github.com/quipucords/quipucords-ui/issues/143)) ([ea98268](https://github.com/quipucords/quipucords-ui/commit/ea982687ad3347cff942782ffc947dd2172ccc1c)) ## 0.10.0 (2022-08-10) ### Bug Fixes -* **build:** base dep package updates ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([e8fb47b](https://github.com/quipucords/quipucords-ui/commit/e8fb47be384272fd18bfbaa426b0232bed1a2d40)) -* **build:** discovery-8 allow repo locale files ([#85](https://github.com/quipucords/quipucords-ui/issues/85)) ([a5a1a0d](https://github.com/quipucords/quipucords-ui/commit/a5a1a0dd3e5e2881f3beb514bf3c28449f7db42c)) -* **build:** npm update, redux middleware ([#82](https://github.com/quipucords/quipucords-ui/issues/82)) ([d0a1aba](https://github.com/quipucords/quipucords-ui/commit/d0a1aba0c498067531ca335983897b622b31aa5f)) -* **build:** npm updates ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([b1ec470](https://github.com/quipucords/quipucords-ui/commit/b1ec470eb25ab27169d7eec94b47629f4177b227)) -* **build:** npm updates ([#83](https://github.com/quipucords/quipucords-ui/issues/83)) ([29afd8f](https://github.com/quipucords/quipucords-ui/commit/29afd8f2ed4804a3a385c5c2938a2406ebb3b790)) -* **build:** update react ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([1fdb58c](https://github.com/quipucords/quipucords-ui/commit/1fdb58c108b2adb1b72a9204d5946f2572c2c639)) -* **i18n:** component loading ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([e904e0d](https://github.com/quipucords/quipucords-ui/commit/e904e0d663836a0dee40f6960cc4d81b3c99ddcc)) +- **build:** base dep package updates ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([e8fb47b](https://github.com/quipucords/quipucords-ui/commit/e8fb47be384272fd18bfbaa426b0232bed1a2d40)) +- **build:** discovery-8 allow repo locale files ([#85](https://github.com/quipucords/quipucords-ui/issues/85)) ([a5a1a0d](https://github.com/quipucords/quipucords-ui/commit/a5a1a0dd3e5e2881f3beb514bf3c28449f7db42c)) +- **build:** npm update, redux middleware ([#82](https://github.com/quipucords/quipucords-ui/issues/82)) ([d0a1aba](https://github.com/quipucords/quipucords-ui/commit/d0a1aba0c498067531ca335983897b622b31aa5f)) +- **build:** npm updates ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([b1ec470](https://github.com/quipucords/quipucords-ui/commit/b1ec470eb25ab27169d7eec94b47629f4177b227)) +- **build:** npm updates ([#83](https://github.com/quipucords/quipucords-ui/issues/83)) ([29afd8f](https://github.com/quipucords/quipucords-ui/commit/29afd8f2ed4804a3a385c5c2938a2406ebb3b790)) +- **build:** update react ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([1fdb58c](https://github.com/quipucords/quipucords-ui/commit/1fdb58c108b2adb1b72a9204d5946f2572c2c639)) +- **i18n:** component loading ([#80](https://github.com/quipucords/quipucords-ui/issues/80)) ([e904e0d](https://github.com/quipucords/quipucords-ui/commit/e904e0d663836a0dee40f6960cc4d81b3c99ddcc)) ### Code Refactoring -* **redux:** discovery-8 middleware, hooks, restructure ([#82](https://github.com/quipucords/quipucords-ui/issues/82)) ([acabcf8](https://github.com/quipucords/quipucords-ui/commit/acabcf827f17d5755a7bc303ca49829fea5158bb)) -* **services:** discovery-8 minor config restructure ([#82](https://github.com/quipucords/quipucords-ui/issues/82)) ([90a4dfd](https://github.com/quipucords/quipucords-ui/commit/90a4dfdf9a536484b793cfe4ee4926652d70f506)) +- **redux:** discovery-8 middleware, hooks, restructure ([#82](https://github.com/quipucords/quipucords-ui/issues/82)) ([acabcf8](https://github.com/quipucords/quipucords-ui/commit/acabcf827f17d5755a7bc303ca49829fea5158bb)) +- **services:** discovery-8 minor config restructure ([#82](https://github.com/quipucords/quipucords-ui/issues/82)) ([90a4dfd](https://github.com/quipucords/quipucords-ui/commit/90a4dfdf9a536484b793cfe4ee4926652d70f506)) ## 0.9.3 (2020-05-14) ### Bug Fixes -* **addSourceWizardStepTwo:** issues/77 add source regex ([#78](https://github.com/quipucords/quipucords-ui/issues/78)) ([3d1aeea](https://github.com/quipucords/quipucords-ui/commit/3d1aeea)) -* **build:** file lint updates ([2919e90](https://github.com/quipucords/quipucords-ui/commit/2919e90)) -* **build:** npm updates and linting ([dc5cbdf](https://github.com/quipucords/quipucords-ui/commit/dc5cbdf)) +- **addSourceWizardStepTwo:** issues/77 add source regex ([#78](https://github.com/quipucords/quipucords-ui/issues/78)) ([3d1aeea](https://github.com/quipucords/quipucords-ui/commit/3d1aeea)) +- **build:** file lint updates ([2919e90](https://github.com/quipucords/quipucords-ui/commit/2919e90)) +- **build:** npm updates and linting ([dc5cbdf](https://github.com/quipucords/quipucords-ui/commit/dc5cbdf)) ## 0.9.2 (2019-12-12) ### Bug Fixes -* **build:** issues/73 correct Django token reference ([#74](https://github.com/quipucords/quipucords-ui/issues/74)) ([06966d4](https://github.com/quipucords/quipucords-ui/commit/06966d4)) +- **build:** issues/73 correct Django token reference ([#74](https://github.com/quipucords/quipucords-ui/issues/74)) ([06966d4](https://github.com/quipucords/quipucords-ui/commit/06966d4)) ## 0.9.1 (2019-08-20) ### Bug Fixes -* **build:** issues/53 brand, contribution guide ([#65](https://github.com/quipucords/quipucords-ui/issues/65)) ([10d4a37](https://github.com/quipucords/quipucords-ui/commit/10d4a37)) -* **build:** issues/60 jenkins file for branded UI ([#67](https://github.com/quipucords/quipucords-ui/issues/67)) ([14b6d95](https://github.com/quipucords/quipucords-ui/commit/14b6d95)) -* **build:** issues/63 Quipudocs package ([#66](https://github.com/quipucords/quipucords-ui/issues/66)) ([354a5bf](https://github.com/quipucords/quipucords-ui/commit/354a5bf)) -* **quipudocs, pageLayout:** issues/68 disable install guide ([#69](https://github.com/quipucords/quipucords-ui/issues/69)) ([2cdf23f](https://github.com/quipucords/quipucords-ui/commit/2cdf23f)) +- **build:** issues/53 brand, contribution guide ([#65](https://github.com/quipucords/quipucords-ui/issues/65)) ([10d4a37](https://github.com/quipucords/quipucords-ui/commit/10d4a37)) +- **build:** issues/60 jenkins file for branded UI ([#67](https://github.com/quipucords/quipucords-ui/issues/67)) ([14b6d95](https://github.com/quipucords/quipucords-ui/commit/14b6d95)) +- **build:** issues/63 Quipudocs package ([#66](https://github.com/quipucords/quipucords-ui/issues/66)) ([354a5bf](https://github.com/quipucords/quipucords-ui/commit/354a5bf)) +- **quipudocs, pageLayout:** issues/68 disable install guide ([#69](https://github.com/quipucords/quipucords-ui/issues/69)) ([2cdf23f](https://github.com/quipucords/quipucords-ui/commit/2cdf23f)) ### Features -* **docs:** issues/38 integrate documentation ([#62](https://github.com/quipucords/quipucords-ui/issues/62)) ([d21d47f](https://github.com/quipucords/quipucords-ui/commit/d21d47f)) +- **docs:** issues/38 integrate documentation ([#62](https://github.com/quipucords/quipucords-ui/issues/62)) ([d21d47f](https://github.com/quipucords/quipucords-ui/commit/d21d47f)) ## 0.9.0 (2019-06-13) ### Bug Fixes -* **addSourceWizard:** copy updates ([#26](https://github.com/quipucords/quipucords-ui/issues/26)) ([2107682](https://github.com/quipucords/quipucords-ui/commit/2107682)) -* **app, auth, pageLayout, router:** issues/18 migrate prep pf4 ([#47](https://github.com/quipucords/quipucords-ui/issues/47)) ([98b8da3](https://github.com/quipucords/quipucords-ui/commit/98b8da3)) -* **build:** issues/29 version display ([#43](https://github.com/quipucords/quipucords-ui/issues/43)) ([e48a322](https://github.com/quipucords/quipucords-ui/commit/e48a322)) -* **build:** issues/50 clean up docker review env ([#55](https://github.com/quipucords/quipucords-ui/issues/55)) ([6bf20ec](https://github.com/quipucords/quipucords-ui/commit/6bf20ec)) -* **confirmation, formState, app, about, masthead, redux:** issues/1 ([#10](https://github.com/quipucords/quipucords-ui/issues/10)) ([496df34](https://github.com/quipucords/quipucords-ui/commit/496df34)) -* **createScanDialog:** issues/28 concurrency default ([#32](https://github.com/quipucords/quipucords-ui/issues/32)) ([5d111e4](https://github.com/quipucords/quipucords-ui/commit/5d111e4)) -* **createScanDialog, helpers:** issues/34 deep scan copy ([#35](https://github.com/quipucords/quipucords-ui/issues/35)) ([98eab26](https://github.com/quipucords/quipucords-ui/commit/98eab26)) -* **credentialListItem, createCredentialDialog:** issues/36 copy ([#37](https://github.com/quipucords/quipucords-ui/issues/37)) ([c4500c0](https://github.com/quipucords/quipucords-ui/commit/c4500c0)) -* **lodash, redux, tooltip:** issues/1 support updates ([#9](https://github.com/quipucords/quipucords-ui/issues/9)) ([7c2328e](https://github.com/quipucords/quipucords-ui/commit/7c2328e)) -* **login, logged_out:** issues/40 copy ([#42](https://github.com/quipucords/quipucords-ui/issues/42)) ([0a5b08b](https://github.com/quipucords/quipucords-ui/commit/0a5b08b)) -* **reportsService:** issues/52 name report package download ([#54](https://github.com/quipucords/quipucords-ui/issues/54)) ([d79bdd5](https://github.com/quipucords/quipucords-ui/commit/d79bdd5)) -* **sourceListItem:** update sources list on delete ([#33](https://github.com/quipucords/quipucords-ui/issues/33)) ([ae2fc83](https://github.com/quipucords/quipucords-ui/commit/ae2fc83)) -* **sources view:** issues/39 network address styling ([#41](https://github.com/quipucords/quipucords-ui/issues/41)) ([6700a9b](https://github.com/quipucords/quipucords-ui/commit/6700a9b)) +- **addSourceWizard:** copy updates ([#26](https://github.com/quipucords/quipucords-ui/issues/26)) ([2107682](https://github.com/quipucords/quipucords-ui/commit/2107682)) +- **app, auth, pageLayout, router:** issues/18 migrate prep pf4 ([#47](https://github.com/quipucords/quipucords-ui/issues/47)) ([98b8da3](https://github.com/quipucords/quipucords-ui/commit/98b8da3)) +- **build:** issues/29 version display ([#43](https://github.com/quipucords/quipucords-ui/issues/43)) ([e48a322](https://github.com/quipucords/quipucords-ui/commit/e48a322)) +- **build:** issues/50 clean up docker review env ([#55](https://github.com/quipucords/quipucords-ui/issues/55)) ([6bf20ec](https://github.com/quipucords/quipucords-ui/commit/6bf20ec)) +- **confirmation, formState, app, about, masthead, redux:** issues/1 ([#10](https://github.com/quipucords/quipucords-ui/issues/10)) ([496df34](https://github.com/quipucords/quipucords-ui/commit/496df34)) +- **createScanDialog:** issues/28 concurrency default ([#32](https://github.com/quipucords/quipucords-ui/issues/32)) ([5d111e4](https://github.com/quipucords/quipucords-ui/commit/5d111e4)) +- **createScanDialog, helpers:** issues/34 deep scan copy ([#35](https://github.com/quipucords/quipucords-ui/issues/35)) ([98eab26](https://github.com/quipucords/quipucords-ui/commit/98eab26)) +- **credentialListItem, createCredentialDialog:** issues/36 copy ([#37](https://github.com/quipucords/quipucords-ui/issues/37)) ([c4500c0](https://github.com/quipucords/quipucords-ui/commit/c4500c0)) +- **lodash, redux, tooltip:** issues/1 support updates ([#9](https://github.com/quipucords/quipucords-ui/issues/9)) ([7c2328e](https://github.com/quipucords/quipucords-ui/commit/7c2328e)) +- **login, logged_out:** issues/40 copy ([#42](https://github.com/quipucords/quipucords-ui/issues/42)) ([0a5b08b](https://github.com/quipucords/quipucords-ui/commit/0a5b08b)) +- **reportsService:** issues/52 name report package download ([#54](https://github.com/quipucords/quipucords-ui/issues/54)) ([d79bdd5](https://github.com/quipucords/quipucords-ui/commit/d79bdd5)) +- **sourceListItem:** update sources list on delete ([#33](https://github.com/quipucords/quipucords-ui/issues/33)) ([ae2fc83](https://github.com/quipucords/quipucords-ui/commit/ae2fc83)) +- **sources view:** issues/39 network address styling ([#41](https://github.com/quipucords/quipucords-ui/issues/41)) ([6700a9b](https://github.com/quipucords/quipucords-ui/commit/6700a9b)) ### Features -* **build:** issues/7 template output tests ([#44](https://github.com/quipucords/quipucords-ui/issues/44)) ([2104ba4](https://github.com/quipucords/quipucords-ui/commit/2104ba4)) -* **build, aboutModal, helpers:** issues/29 version display ([#31](https://github.com/quipucords/quipucords-ui/issues/31)) ([7af215a](https://github.com/quipucords/quipucords-ui/commit/7af215a)) -* **createScanDialog:** issues/1 scan creation options ([#25](https://github.com/quipucords/quipucords-ui/issues/25)) ([c9d5f21](https://github.com/quipucords/quipucords-ui/commit/c9d5f21)) -* **i18n:** issues/38 i18n integration, link to quipudocs ([#51](https://github.com/quipucords/quipucords-ui/issues/51)) ([89ef65c](https://github.com/quipucords/quipucords-ui/commit/89ef65c)) -* **poll, reports:** issues/46 download report package ([#48](https://github.com/quipucords/quipucords-ui/issues/48)) ([8a3c560](https://github.com/quipucords/quipucords-ui/commit/8a3c560)) -* **styling:** issues/6 refresh for brand logos, styling ([#27](https://github.com/quipucords/quipucords-ui/issues/27)) ([e2bb2fc](https://github.com/quipucords/quipucords-ui/commit/e2bb2fc)) +- **build:** issues/7 template output tests ([#44](https://github.com/quipucords/quipucords-ui/issues/44)) ([2104ba4](https://github.com/quipucords/quipucords-ui/commit/2104ba4)) +- **build, aboutModal, helpers:** issues/29 version display ([#31](https://github.com/quipucords/quipucords-ui/issues/31)) ([7af215a](https://github.com/quipucords/quipucords-ui/commit/7af215a)) +- **createScanDialog:** issues/1 scan creation options ([#25](https://github.com/quipucords/quipucords-ui/issues/25)) ([c9d5f21](https://github.com/quipucords/quipucords-ui/commit/c9d5f21)) +- **i18n:** issues/38 i18n integration, link to quipudocs ([#51](https://github.com/quipucords/quipucords-ui/issues/51)) ([89ef65c](https://github.com/quipucords/quipucords-ui/commit/89ef65c)) +- **poll, reports:** issues/46 download report package ([#48](https://github.com/quipucords/quipucords-ui/issues/48)) ([8a3c560](https://github.com/quipucords/quipucords-ui/commit/8a3c560)) +- **styling:** issues/6 refresh for brand logos, styling ([#27](https://github.com/quipucords/quipucords-ui/issues/27)) ([e2bb2fc](https://github.com/quipucords/quipucords-ui/commit/e2bb2fc)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e3e1f680..0d391857d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,17 +1,21 @@ # Contributing + Contributing encompasses repository specific requirements, and the global [Quipucords contribution guidelines](https://github.com/quipucords/quipucords/blob/main/CONTRIBUTING.md). ## Process +

Using Git

Quipucords-UI makes use of + - GitHub's fork and pull workflow. - A linear commit process and rebasing. > Instead of relying on GitHub merge commits and squashing, we recommend breaking down changes into smaller, independent commits. #### Branch syncing + Linear commit history for Quipucords-UI simplifies understanding and syncing changes across branches. Do not use merge commits. Always use fast-forward rebase. New changes must be made in a branch and be submitted via GitHub pull requests. PRs should target merging to `main`. @@ -24,17 +28,19 @@ New changes must be made in a branch and be submitted via GitHub pull requests. All development work should be handled through GitHub's fork and pull workflow. #### Setting up a pull request + When multiple developers are contributing features, development pull requests (PRs) should be opened against the `main` branch. > If your pull request work contains any of the following warning signs -> - out of sync commits (is not rebased against the `base branch`) -> - poorly structured commits and messages -> - any one commit relies on other commits to work at all, in the same pull request -> - dramatic file restructures that attempt complex behavior -> - missing, relaxed, or removed unit tests -> - dramatic unit test snapshot updates -> - affects any file not directly associated with the issue being resolved -> - affects "many" files +> +> - out of sync commits (is not rebased against the `base branch`) +> - poorly structured commits and messages +> - any one commit relies on other commits to work at all, in the same pull request +> - dramatic file restructures that attempt complex behavior +> - missing, relaxed, or removed unit tests +> - dramatic unit test snapshot updates +> - affects any file not directly associated with the issue being resolved +> - affects "many" files > > You may be encouraged to restructure your commits to help in review. @@ -44,8 +50,10 @@ Your pull request should contain Git commit messaging that follows the use of [c to provide consistent history and help generate [CHANGELOG.md](./CHANGELOG.md) updates. Commit messages follow three basic guidelines + - No more than `65` characters for the first line - If your pull request has more than a single commit you should include the pull request number in your message using the below format. This additional copy is not counted towards the `65` character limit. + ``` [message] (#1234) ``` @@ -55,10 +63,13 @@ Commit messages follow three basic guidelines `squash` button is used on a pull request. - Commit message formats follow the structure + ``` (): ``` + Where + - Type = the type of work the commit resolves. - Basic types include `feat` (feature), `fix`, `chore`, `build`. - See [conventional commit types](https://www.conventionalcommits.org/) for additional types. @@ -70,19 +81,24 @@ Commit messages follow three basic guidelines - Description = what the commit work encompasses Example + ``` feat(scans): dis-123 activate foo against bar ``` -> Not all commits need an issue number. But it is encouraged you attempt to associate -> a commit with an issue for tracking. In a scenario where no issue is available -> exceptions can be made for `fix`, `chore`, and `build`. + + > Not all commits need an issue number. But it is encouraged you attempt to associate + > a commit with an issue for tracking. In a scenario where no issue is available + > exceptions can be made for `fix`, `chore`, and `build`. #### Pull request test failures + Creating a pull request activates the following checks through GitHub actions. + - Commit message linting, see [commit_lint.yml](./.github/workflows/commit_lint.yml) - Pull request code linting, unit tests and repo-level integration tests, see [integration.yml](./.github/workflows/integration.yml) For additional information on failures for + - Commit messages, see [Pull request commits, messaging](#pull-request-commits-messaging) - Code documentation, see [Updating code documentation]() - Pull request code, see [Updating unit tests during development]() @@ -108,9 +124,11 @@ For additional information on failures for quipucords-ui uses GitHub releases, and our GitHub automation automatically builds and attaches artifacts to a release once its tag is created. See [integration.yml](https://github.com/quipucords/quipucords-ui/blob/main/.github/workflows/integration.yml) for implementation details and [Build workflow](https://github.com/quipucords/quipucords-ui/actions/workflows/integration.yml?query=event%3Apush) for the history of workflow runs. #### Release artifacts + To create a new release, use `yarn` to update version details, and open a PR to merge those changes to `main` using the following process. 1. Within the repo, confirm you're on a new branch from the latest `main`, and use `yarn` to update the version: + ``` git checkout main && git pull # to ensure you have the latest changes git checkout -b your-release-branch-name # please use an appropriate branch name here @@ -120,20 +138,25 @@ To create a new release, use `yarn` to update version details, and open a PR to ``` > If you disagree with automatic generated version number, you may override it with the > optional `--override` argument: + > > ``` > yarn release --override X.X.X > ``` + 2. Confirm you now have a release commit with the format `chore(release): X.X.X` that includes changes to: + - [`package.json`](./package.json) - [`CHANGELOG.md`](./CHANGELOG.md) If there are issues with the file updates, please squash or amend any fixes into the single `chore(release): X.X.X` commit. + 3. Push the **SINGLE** commit to a new branch on the remote GitHub origin: ``` git push --set-upstream origin your-release-branch-name ``` 4. Open a PR in GitHub for your branch to merge into `main`. Get approvals, and merge. 5. Using the [GitHub releases page](https://github.com/RedHatInsights/quipucords-ui/releases): + 1. Draft a new release from `main`, and confirm it references your latest `chore(release): X.X.X` commit hash. 2. Create the new tag using the **SAME** semver version created by the release commit, i.e. `X.X.X`. @@ -146,14 +169,17 @@ To create a new release, use `yarn` to update version details, and open a PR to

NPM maintenance

#### Cycle for updating NPMs + Our schedule for updating NPMs + - dependabot running once a month on low level packages that require only testing confirmation to pass - 1x a month: running our aggregated dependency update script for all low level packages that require only testing confirmation - `$ yarn build:deps` - 1x a month: running updates on NPMs that require additional visual confirmation, this includes... - - dependency-name: "@patternfly/*" + - dependency-name: "@patternfly/\*" #### Process for updating NPMs + To update packages in bulk there are 2 pre-defined paths, "basic" and "core". > It is **highly discouraged** that you rely on updating the `yarn.lock` file only. This creates long-term issues when NPM references in `package.json` potentially require specific @@ -166,57 +192,62 @@ To update packages in bulk there are 2 pre-defined paths, "basic" and "core". 1. Clone the repository locally, or bring your fork up-to-date with the `main` branch. [Make sure development tooling is installed](#install-tooling). 1. Open a terminal instance in the repository context and run - ``` - $ yarn build:deps - ``` + ``` + $ yarn build:deps + ``` This will cycle through ALL basic NPM dependencies, running both unit tests, build and local integration checks. If any errors are throw the package update is skipped. 1. After the updates have completed **YOU MUST VISUALLY CONFIRM** the updates were successful by running both local development start scripts. - Visually confirm that local development still functions and can be navigated with... - 1. Start VPN, and make sure Docker/Podman is running. - 1. Run - ``` - $ yarn start - ``` + 1. Start VPN, and make sure Docker/Podman is running. + 1. Run + ``` + $ yarn start + ``` - Visually confirm that staging development still functions and can be navigated with... - 1. Start VPN, and make sure Docker/Podman is running. - 1. Run - ``` - $ yarn start:stage - ``` + 1. Start VPN, and make sure Docker/Podman is running. + 1. Run + ``` + $ yarn start:stage + ``` 1. After you've confirmed everything is functioning correctly, check and commit the related changes to `package.json` and `yarn.lock`, then open a pull request towards the `main` branch. -> If any part of the "basic path" process fails you'll need to figure out which NPM is the offender and remove it from the update. OR resolve to fix the issue -> since future updates will be affected by skipping any package update. -> A `dependency-update-log.txt" file is generated in the root of the repository after each run of `$ yarn build:deps` this should contain a listing of the skipped packages. + > If any part of the "basic path" process fails you'll need to figure out which NPM is the offender and remove it from the update. OR resolve to fix the issue + > since future updates will be affected by skipping any package update. + > A `dependency-update-log.txt" file is generated in the root of the repository after each run of `$ yarn build:deps` this should contain a listing of the skipped packages. ##### Core NPM updates + 1. Clone the repository locally, or bring your fork up-to-date with the `main` branch. [Make sure development tooling is installed](#install-tooling). 1. Open a terminal instance in the repository context and run - ``` - $ yarn build:deps-core - ``` + ``` + $ yarn build:deps-core + ``` This will cycle through ALL core NPM dependencies, running both unit tests, build and local integration checks. If any errors are throw the package update is skipped. 1. After the updates have completed **YOU MUST VISUALLY CONFIRM** the updates were successful by running both local development start scripts. - Visually confirm that local development still functions and can be navigated with... - 1. Start VPN, and make sure Docker/Podman is running. - 1. Run - ``` - $ yarn start - ``` - - Visually confirm that staging development still functions and can be navigated with... 1. Start VPN, and make sure Docker/Podman is running. 1. Run ``` - $ yarn start:stage + $ yarn start ``` + +- Visually confirm that staging development still functions and can be navigated with... + 1. Start VPN, and make sure Docker/Podman is running. + 1. Run + ``` + $ yarn start:stage + ``` + 1. After you've confirmed everything is functioning correctly, check and commit the related changes to `package.json` and `yarn.lock`, then open a pull request towards the `main` branch. -> If any part of the "core path" process fails you'll need to figure out which NPM is the offender and remove it from the update. OR resolve to fix the issue -> since future updates will be affected by skipping potentially any package update. -> A `dependency-update-log.txt" file is generated in the root of the repository after each run of `$ yarn build:deps-core` this should contain a listing of the skipped packages. + > If any part of the "core path" process fails you'll need to figure out which NPM is the offender and remove it from the update. OR resolve to fix the issue + > since future updates will be affected by skipping potentially any package update. + > A `dependency-update-log.txt" file is generated in the root of the repository after each run of `$ yarn build:deps-core` this should contain a listing of the skipped packages. ##### Manual NPM updates + This is the slowest part of package updates. If any packages are skipped during the "basic" and "core" automation runs. Those packages will need to be updated manually. + 1. Clone the repository locally, or bring your fork up-to-date, with the `main` branch. [Make sure development tooling is installed](#install-tooling). 1. Remove/delete the `node_modules` directory (there may be differences between branches that create package alterations) 1. Run @@ -233,9 +264,9 @@ This is the slowest part of package updates. If any packages are skipped during - Make sure Docker/Podman is running, then type `$ yarn start:stage`. Confirm that staging run is still accessible and that no design alterations have happened. Fix accordingly. 1. If the package is now working commit the change and move on to the next package. - If the package fails, or you want to skip the update, take the minimally easy path and remove/delete `node_modules` then rollback `yarn.lock` **BEFORE** you run the next package update. -> There are alternatives to resetting `node_modules`, we're providing the most direct path. -> -> Not updating a package is not the end-of-the-world. A package is not going to randomly break because you haven't updated to the latest version. + > There are alternatives to resetting `node_modules`, we're providing the most direct path. + > + > Not updating a package is not the end-of-the-world. A package is not going to randomly break because you haven't updated to the latest version. > Security warnings on NPM packages should be reviewed on a "per-alert basis" since **they generally do not make a distinction between build resources and what is within the applications compiled output**. Blindly following a security > update recommendation is not always the optimal path. @@ -253,21 +284,23 @@ This is the slowest part of package updates. If any packages are skipped during - GitHub Actions - Action files - [`./.github/workflows`](.github/workflows) - - Related script files - - [`./.scripts/actions.commit.js`](./scripts/actions.commit.js) -
+ - Related script files - [`./.scripts/actions.commit.js`](./scripts/actions.commit.js) + ## Development +

Install tooling

Before developing you'll need to install: -* [NodeJS and NPM](https://nodejs.org/) -* [Docker](https://docs.docker.com/desktop/) - * Alternatively, you can try [Podman](https://github.com/containers/podman). [Homebrew](https://brew.sh/) can be used for the install `$ brew install podman` -* And [Yarn](https://yarnpkg.com) + +- [NodeJS and NPM](https://nodejs.org/) +- [Docker](https://docs.docker.com/desktop/) + - Alternatively, you can try [Podman](https://github.com/containers/podman). [Homebrew](https://brew.sh/) can be used for the install `$ brew install podman` +- And [Yarn](https://yarnpkg.com) #### OS support + The tooling for Quipucords-UI is `Mac OS` centered. While some aspects of the tooling have been expanded for Linux there may still be issues. It is encouraged that OS tooling @@ -276,10 +309,13 @@ changes are contributed back while maintaining existing `Mac OS` functionality. If you are unable to test additional OS support it is imperative that code reviews take place before integrating/merging build changes. #### NodeJS and NPM + The Quipucords-UI build attempts to align to the current NodeJS LTS version. It is possible to test future versions of NodeJS LTS. See CI Testing for more detail. #### Docker and Mac + Setting [Docker](https://docs.docker.com/desktop/) up on a Mac? Install the appropriate package. Confirm everything installed correctly by trying these steps. + 1. In a terminal instance run ``` $ docker run hello-world @@ -288,17 +324,21 @@ Setting [Docker](https://docs.docker.com/desktop/) up on a Mac? Install the appr Reference the Docker documentation for additional installation help. #### Docker and Linux + Setting Docker up on a Linux machine may include additional steps. -* [Docker on Linux](https://docs.docker.com/desktop/install/linux-install/) + +- [Docker on Linux](https://docs.docker.com/desktop/install/linux-install/) Reference the Docker documentation for additional installation help. #### Yarn + Once you've installed NodeJS you can use NPM to perform the [Yarn](https://yarnpkg.com) install - ``` - $ npm install yarn -g - ``` +``` +$ npm install yarn -g +``` +
@@ -307,16 +347,19 @@ Once you've installed NodeJS you can use NPM to perform the [Yarn](https://yarnp "dotenv" files contain shared configuration settings across the Quipucords-UI code and build structure. These settings are imported through [helpers](./src/common/helpers.js), or through other various `process.env.[dotenv parameter names]` within the code or build. #### Setup basic dotenv files + Before you can start any local development you need to relax permissions associated with the platform. This affects various aspects of both `local` and `stage` development. 1. Create a local dotenv file in the root of `Quipucords-UI` called `.env.local` and add the following contents - ``` - REACT_APP_DEBUG_MIDDLEWARE=true - ``` + ``` + REACT_APP_DEBUG_MIDDLEWARE=true + ``` #### Advanced dotenv files + The dotenv files are structured to cascade each additional dotenv file settings from a root `.env` file. + ``` .env = base dotenv file settings .env.local = a gitignored file to allow local settings overrides @@ -331,13 +374,11 @@ The dotenv files are structured to cascade each additional dotenv file settings > Technically all dotenv parameters come across as strings when imported through `process.env`. It is important to cast them accordingly if "type" is required. - | dotenv parameter | definition | | -------------------------- | ------------------------------------------------------------------------------------------ | | REACT_APP_AUTH_TOKEN | A static string associated with overriding the assumed UI/application token name | | REACT_APP_DEBUG_MIDDLEWARE | A static boolean that activates the console state debugging messages associated with Redux | - ##### Current directly available _build_ dotenv parameters > Technically all dotenv parameters come across as strings when imported through `process.env`. It is important to cast them accordingly if "type" is required. @@ -389,15 +430,16 @@ The dotenv files are structured to cascade each additional dotenv file settings

Local and staging development

#### Start writing code with local run + This is a local run designed to function with minimal resources and a mock API. 1. Confirm you've installed all recommended tooling 1. Confirm the repository name has no blank spaces in it. If it does replace that blank with a dash or underscore, Docker has issues with unescaped parameter strings. 1. Confirm you've installed resources through yarn 1. Create a local dotenv file called `.env.local` in the root of Quipucords-UI, and add the following contents - ``` - REACT_APP_DEBUG_MIDDLEWARE=true - ``` + ``` + REACT_APP_DEBUG_MIDDLEWARE=true + ``` 1. Make sure Docker/Podman is running 1. Open a couple of instances of Terminal and run... ``` @@ -411,24 +453,25 @@ This is a local run designed to function with minimal resources and a mock API. 1. Start developing... #### Start writing code with staging + This is an authenticated local run that has the ability to run against a containerized API. 1. Confirm you've installed all recommended tooling 1. Confirm the repository name has no blank spaces in it. If it does replace that blank with a dash or underscore, Docker has issues with unescaped parameter strings. 1. Confirm you've installed resources through yarn 1. Create a local dotenv file called `.env.local` in the root of Quipucords-UI, and add the following contents - ``` - REACT_APP_DEBUG_MIDDLEWARE=true - ``` + ``` + REACT_APP_DEBUG_MIDDLEWARE=true + ``` 1. Make sure Docker/Podman is running 1. Open a couple of instances of Terminal and run... - ``` - $ yarn start:stage - ``` + ``` + $ yarn start:stage + ``` and, optionally, - ``` - $ yarn test:dev - ``` + ``` + $ yarn test:dev + ``` 1. Make sure you open your browser around the domain `https://localhost:5001/` > You may have to scroll, but the terminal output will have some available domains for you to pick from. 1. Log in. (You'll need mock credentials, reach out to the development team) @@ -436,12 +479,13 @@ This is an authenticated local run that has the ability to run against a contain
-

Reserved CSS classNames, and attributes

#### Reserved testing attributes + This project makes use of reserved DOM attributes and string identifiers used by the testing team. + > Updating elements with these attributes, or settings, should be done with the knowledge "you are affecting" the testing team's ability to test. > And it is recommended you coordinate with the testing team before altering these attributes, settings. @@ -462,38 +506,47 @@ This project makes use of reserved DOM attributes and string identifiers used by This repository has interdependency on the [Quipucords responsitory](https://github.com/quipucords/quipucords). #### Django templates, login and logout + In order to have GUI developer access to the login and logout aspects of [Quipucords](https://github.com/quipucords/quipucords) we store -the Django template files here [./templates/*](./templates/base.html). +the Django template files here [./templates/\*](./templates/base.html). > Important! +> > - This templates directory is required as part of the build process. **Removing `./templates` directory will break the production build.** > - Updating the templates requires minimal understand of html, plus some minor recognition of templating languages. [If needed checkout out the Django template structure reading](https://docs.djangoproject.com/en/2.1/topics/templates/). > - We use a shell script token string replacement during the build process for the application display name. If you see **[UI_NAME]** within the templates, be aware. > - [The build script for directly manipulating the templates is here, ./scripts/post.sh](./scripts/post.sh) #### Brand build + The brand build updates aspects of the application name across the React and Django templates, think Quipucords versus Discovery. To handle a branded aspect of the build, instead of `$ yarn build` run - ``` - $ yarn build:brand - ``` + +``` +$ yarn build:brand +``` +

Debugging

#### Debugging development + You can apply overrides during local development by adding a `.env.local` (dotenv) file in the repository root directory. Once you have made the dotenv file and/or changes, like the below "debug" flags, restart the project and the flags should be active. -*Any changes you make to the `.env.local` file should be ignored with `.gitignore`.* +_Any changes you make to the `.env.local` file should be ignored with `.gitignore`._ #### Debugging Redux + This project makes use of React & Redux. To enable Redux browser console logging add the following line to your `.env.local` file. - ``` - REACT_APP_DEBUG_MIDDLEWARE=true - ``` + +``` +REACT_APP_DEBUG_MIDDLEWARE=true +``` +
@@ -504,41 +557,54 @@ This project makes use of React & Redux. To enable Redux browser console logging > line of checks against bugs/issues. #### Unit testing + To run the unit tests with a watch during development you'll need to open an additional terminal instance, then run - ``` - $ yarn test:dev - ``` + +``` +$ yarn test:dev +``` ##### Updating test snapshots + To update snapshots from the terminal run - ``` - $ yarn test:dev - ``` + +``` +$ yarn test:dev +``` From there you'll be presented with a few choices, one of them is "update", you can then hit the "u" key. Once the update script has run you should see additional changed files within Git, make sure to commit them along with your changes or continuous integration testing will fail. ##### Checking code coverage + To check the coverage report from the terminal run - ``` - $ yarn test - ``` + +``` +$ yarn test +``` ##### Code coverage failing to update? + If you're having trouble getting an accurate code coverage report, or it's failing to provide updated results (i.e. you renamed files) you can try running - ``` - $ yarn test:clearCache - ``` + +``` +$ yarn test:clearCache +``` #### Integration-like testing + To run tests associated with checking build output run - ``` - $ yarn build - $ yarn test:integration - ``` + +``` +$ yarn build +$ yarn test:integration +``` ##### Updating integration-like test snapshots + To update snapshots from the terminal run - ``` - $ yarn test:integration-dev - ``` + +``` +$ yarn test:integration-dev +``` +
diff --git a/README.md b/README.md index 3538aedf5..52b47bde7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Quipucords UI + [![Build Status](https://github.com/quipucords/quipucords-ui/actions/workflows/integration.yml/badge.svg)](https://github.com/quipucords/quipucords-ui/actions/workflows/integration.yml) [![codecov](https://codecov.io/gh/quipucords/quipucords-ui/branch/main/graph/badge.svg)](https://codecov.io/gh/quipucords/quipucords-ui) [![License](https://img.shields.io/github/license/quipucords/quipucords-ui.svg)](https://github.com/quipucords/quipucords-ui/blob/main/LICENSE) @@ -8,31 +9,36 @@ Web user interface for [Quipucords](https://github.com/quipucords/quipucords), b ## Development, Quick Start ### Requirements + Before developing, the basic requirements: - * Your system needs to be running [NodeJS version 18+ and NPM](https://nodejs.org/) - * [Docker](https://docs.docker.com/desktop/) - * Alternatively, you can try [Podman](https://github.com/containers/podman). - * And [Yarn](https://yarnpkg.com) for dependency and script management. + +- Your system needs to be running [NodeJS version 18+ and NPM](https://nodejs.org/) +- [Docker](https://docs.docker.com/desktop/) + - Alternatively, you can try [Podman](https://github.com/containers/podman). +- And [Yarn](https://yarnpkg.com) for dependency and script management. For in-depth tooling install guidance see the [contribution guidelines](./CONTRIBUTING.md#install-tooling) ### Installing - 1. Clone the repository - ``` - $ git clone https://github.com/quipucords/quipucords-ui.git - ``` - 1. Within the repo context, install project dependencies - ``` - $ cd quipucords-ui && yarn - ``` +1. Clone the repository + + ``` + $ git clone https://github.com/quipucords/quipucords-ui.git + ``` + +1. Within the repo context, install project dependencies + ``` + $ cd quipucords-ui && yarn + ``` ### Develop + This is the base context for running a local UI against a mock API. 1. Create a local dotenv file called `.env.local` and add the following contents - ``` - REACT_APP_DEBUG_MIDDLEWARE=true + ``` + REACT_APP_DEBUG_MIDDLEWARE=true ``` 1. Make sure Docker/Podman is running 1. In a terminal instance that uses the repo context... Run @@ -44,6 +50,7 @@ This is the base context for running a local UI against a mock API. For in-depth local run guidance review the [contribution guidelines](./CONTRIBUTING.md#local-and-stage-development) ### Unit testing + Run and update unit tests while developing instead of after-the-fact. In a new terminal instance 1. In a new terminal instance that uses the repo context... Run @@ -56,4 +63,5 @@ Run and update unit tests while developing instead of after-the-fact. In a new t For in-depth testing guidance review the [contribution guidelines](./CONTRIBUTING.md#testing) ## Contributing + Contributing encompasses [repository specific requirements](./CONTRIBUTING.md) and the global [contribution guidelines](https://github.com/quipucords/quipucords/blob/main/CONTRIBUTING.md). diff --git a/__mocks__/fileMock.js b/__mocks__/fileMock.js index 84c1da6fd..86059f362 100644 --- a/__mocks__/fileMock.js +++ b/__mocks__/fileMock.js @@ -1 +1 @@ -module.exports = 'test-file-stub'; \ No newline at end of file +module.exports = 'test-file-stub'; diff --git a/__mocks__/styleMock.js b/__mocks__/styleMock.js index a09954537..f053ebf79 100644 --- a/__mocks__/styleMock.js +++ b/__mocks__/styleMock.js @@ -1 +1 @@ -module.exports = {}; \ No newline at end of file +module.exports = {}; diff --git a/babel.config.js b/babel.config.js index b2ac2a3f7..e65a9c08c 100644 --- a/babel.config.js +++ b/babel.config.js @@ -8,5 +8,5 @@ module.exports = { browserslist?.production?.join(', ') || 'entry', presets: ['@babel/preset-env', '@babel/preset-react'], - plugins: ['@babel/plugin-transform-runtime'] + plugins: ['@babel/plugin-transform-runtime'], }; diff --git a/config/README.md b/config/README.md index 52b4d94ee..84bc62a7c 100644 --- a/config/README.md +++ b/config/README.md @@ -1,6 +1,9 @@ # Configuration + ## Build + Build support scripts. ## Testing + Jest configuration setup and transform scripts. diff --git a/config/build.dotenv.js b/config/build.dotenv.js index ba0d70704..01489f135 100644 --- a/config/build.dotenv.js +++ b/config/build.dotenv.js @@ -9,10 +9,10 @@ const { expand: dotenvExpand } = require('dotenv-expand'); * @param {string} filePath * @returns {*} */ -const setupWebpackDotenvFile = filePath => { +const setupWebpackDotenvFile = (filePath) => { const settings = { systemvars: true, - silent: true + silent: true, }; if (filePath) { @@ -43,7 +43,7 @@ const setupWebpackDotenvFilesForEnv = ({ directory, env } = {}) => { if (env) { dotenvWebpackSettings.push( - setupWebpackDotenvFile(path.resolve(directory, `.env.${env}.local`)) + setupWebpackDotenvFile(path.resolve(directory, `.env.${env}.local`)), ); dotenvWebpackSettings.push(setupWebpackDotenvFile(path.resolve(directory, `.env.${env}`))); } @@ -60,7 +60,7 @@ const setupWebpackDotenvFilesForEnv = ({ directory, env } = {}) => { * @param {string} filePath * @returns {void} */ -const setupDotenvFile = filePath => { +const setupDotenvFile = (filePath) => { const dotenvInitial = dotenv.config({ path: filePath }); dotenvExpand(dotenvInitial); }; @@ -79,7 +79,7 @@ const setupDotenvFilesForEnv = ({ env, relativePath = path.resolve(__dirname, '..'), dotenvNamePrefix = 'BUILD', - setBuildDefaults = true + setBuildDefaults = true, } = {}) => { if (env) { setupDotenvFile(path.resolve(relativePath, `.env.${env}.local`)); @@ -95,7 +95,7 @@ const setupDotenvFilesForEnv = ({ process.env[`${dotenvNamePrefix}_DEV_MODE`] || process.env.DEV_MODE || undefined; const DIST_DIR = path.resolve( relativePath, - process.env[`${dotenvNamePrefix}_DIST_DIR`] || process.env.DIST_DIR || 'dist' + process.env[`${dotenvNamePrefix}_DIST_DIR`] || process.env.DIST_DIR || 'dist', ); const HOST = process.env[`${dotenvNamePrefix}_HOST`] || process.env.HOST || 'localhost'; const OUTPUT_ONLY = process.env[`_${dotenvNamePrefix}_OUTPUT_ONLY`] === 'true'; @@ -106,11 +106,11 @@ const setupDotenvFilesForEnv = ({ process.env[`${dotenvNamePrefix}_PUBLIC_PATH`] || process.env.PUBLIC_PATH || '/'; const SRC_DIR = path.resolve( relativePath, - process.env[`${dotenvNamePrefix}_SRC_DIR`] || process.env.SRC_DIR || 'src' + process.env[`${dotenvNamePrefix}_SRC_DIR`] || process.env.SRC_DIR || 'src', ); const STATIC_DIR = path.resolve( relativePath, - process.env[`${dotenvNamePrefix}_STATIC_DIR`] || process.env.STATIC_DIR || 'public' + process.env[`${dotenvNamePrefix}_STATIC_DIR`] || process.env.STATIC_DIR || 'public', ); // Build Extras - Display name, HTML title diff --git a/config/jest.setupTests.js b/config/jest.setupTests.js index 4bcd23dec..e293c6905 100644 --- a/config/jest.setupTests.js +++ b/config/jest.setupTests.js @@ -14,7 +14,8 @@ setupDotenvFilesForEnv({ env: process.env.NODE_ENV }); * Emulate for component checks */ jest.mock('i18next', () => { - const Test = function () { // eslint-disable-line + const Test = function () { + // eslint-disable-line this.use = () => this; this.init = () => Promise.resolve(); this.changeLanguage = () => Promise.resolve(); @@ -32,7 +33,7 @@ jest.mock('lodash/debounce', () => jest.fn); */ jest.mock('react-redux', () => ({ ...jest.requireActual('react-redux'), - useSelector: jest.fn() + useSelector: jest.fn(), })); /** @@ -41,7 +42,7 @@ jest.mock('react-redux', () => ({ jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: () => jest.fn(), - useLocation: () => ({ hash: '', search: '' }) + useLocation: () => ({ hash: '', search: '' }), })); /** @@ -55,12 +56,14 @@ global.screenRender = { ...screen, render: (containerElement = screen) => { const screenContainer = document.createElement('screen'); - screenContainer.innerHTML = prettyDOM(containerElement.innerHTML, undefined, { highlight: false }) + screenContainer.innerHTML = prettyDOM(containerElement.innerHTML, undefined, { + highlight: false, + }) .replace(/(\s)+/g, ' ') .replace(/>\s<'); return screenContainer; - } + }, }; /** @@ -80,7 +83,7 @@ global.screenRender = { */ global.renderComponent = (testComponent, options = {}) => { const updatedOptions = { includeInstanceRef: true, ...options }; - const getDisplayName = reactComponent => + const getDisplayName = (reactComponent) => reactComponent?.displayName || reactComponent?.$$typeof?.displayName || reactComponent?.$$typeof?.name || @@ -92,12 +95,12 @@ global.renderComponent = (testComponent, options = {}) => { displayName: getDisplayName(testComponent), props: { ...testComponent?.props, - children: React.Children.toArray(testComponent?.props?.children).map(child => ({ + children: React.Children.toArray(testComponent?.props?.children).map((child) => ({ displayName: getDisplayName(child), props: child?.props, - type: child?.type - })) - } + type: child?.type, + })), + }, }; const containerElement = document.createElement(componentInfo?.displayName || 'element'); @@ -111,8 +114,11 @@ global.renderComponent = (testComponent, options = {}) => { const updatedTestComponent = { ...testComponent }; let elementInstance; - if (updatedTestComponent?.type?.prototype?.isReactComponent && updatedOptions.includeInstanceRef === true) { - updatedTestComponent.ref = element => { + if ( + updatedTestComponent?.type?.prototype?.isReactComponent && + updatedOptions.includeInstanceRef === true + ) { + updatedTestComponent.ref = (element) => { const updatedElement = element; if (element) { @@ -140,10 +146,10 @@ global.renderComponent = (testComponent, options = {}) => { const { container, ...renderRest } = render(updatedTestComponent, { container: containerElement, queries, - ...updatedOptions + ...updatedOptions, }); - const appendProps = obj => { + const appendProps = (obj) => { Object.entries(renderRest).forEach(([key, value]) => { obj[key] = value; // eslint-disable-line }); @@ -153,10 +159,13 @@ global.renderComponent = (testComponent, options = {}) => { updatedContainer.act = act; updatedContainer.screen = global.screenRender; updatedContainer.instance = elementInstance; - updatedContainer.find = selector => container?.querySelector(selector); + updatedContainer.find = (selector) => container?.querySelector(selector); updatedContainer.fireEvent = fireEvent; - updatedContainer.setProps = updatedProps => { - const updatedComponent = { ...updatedTestComponent, props: { ...updatedTestComponent?.props, ...updatedProps } }; + updatedContainer.setProps = (updatedProps) => { + const updatedComponent = { + ...updatedTestComponent, + props: { ...updatedTestComponent?.props, ...updatedProps }, + }; let rerender = renderRest.rerender(updatedComponent); if (rerender === undefined) { @@ -164,7 +173,7 @@ global.renderComponent = (testComponent, options = {}) => { } if (rerender) { - rerender.find = selector => rerender?.querySelector(selector); + rerender.find = (selector) => rerender?.querySelector(selector); rerender.fireEvent = fireEvent; rerender.setProps = updatedContainer.setProps; appendProps(rerender); @@ -204,7 +213,9 @@ global.renderHook = async (useHook = Function.prototype, options = {}) => { await act(async () => { if (updatedOptions.state) { - spyUseSelector = jest.spyOn(reactRedux, 'useSelector').mockImplementation(_ => _(updatedOptions.state)); + spyUseSelector = jest + .spyOn(reactRedux, 'useSelector') + .mockImplementation((_) => _(updatedOptions.state)); } const { unmount: unmountRender } = await render(); unmountHook = unmountRender; @@ -250,13 +261,14 @@ global.renderHook = async (useHook = Function.prototype, options = {}) => { * @param {React.ReactNode} testComponent * @returns {*} */ -global.shallowComponent = async testComponent => { +global.shallowComponent = async (testComponent) => { const localRenderHook = async (component, updatedProps) => { if (typeof component?.type === 'function') { try { const { unmount, result } = await global.renderHook( - () => component.type({ ...component.type.defaultProps, ...component.props, ...updatedProps }), - { includeInstanceContext: false } + () => + component.type({ ...component.type.defaultProps, ...component.props, ...updatedProps }), + { includeInstanceContext: false }, ); if (!result || typeof result === 'string' || typeof result === 'number') { @@ -273,7 +285,7 @@ global.shallowComponent = async testComponent => { return container.querySelectorAll(sel); }; - const setProps = async p => localRenderHook(component, p); + const setProps = async (p) => localRenderHook(component, p); const renderResult = () => global.renderComponent(result); @@ -295,7 +307,7 @@ global.shallowComponent = async testComponent => { find: querySelector, querySelector, querySelectorAll, - setProps + setProps, }; } catch (e) { // diff --git a/config/jest.transform.file.js b/config/jest.transform.file.js index 360c5ad6c..02a1510d6 100644 --- a/config/jest.transform.file.js +++ b/config/jest.transform.file.js @@ -4,7 +4,7 @@ module.exports = { process(src, filename) { const assetFilename = JSON.stringify(path.basename(filename)); return { - code: `module.exports = ${assetFilename};` + code: `module.exports = ${assetFilename};`, }; - } + }, }; diff --git a/config/jest.transform.style.js b/config/jest.transform.style.js index 684eb9219..735b60935 100644 --- a/config/jest.transform.style.js +++ b/config/jest.transform.style.js @@ -1,10 +1,10 @@ module.exports = { process() { return { - code: 'module.exports = {};' + code: 'module.exports = {};', }; }, getCacheKey() { return 'cssTransform'; - } + }, }; diff --git a/config/webpack.common.js b/config/webpack.common.js index 58ad276ed..87aa5318e 100644 --- a/config/webpack.common.js +++ b/config/webpack.common.js @@ -17,12 +17,12 @@ const { _BUILD_RELATIVE_DIRNAME: RELATIVE_DIRNAME, _BUILD_SRC_DIR: SRC_DIR, _BUILD_STATIC_DIR: STATIC_DIR, - _BUILD_UI_NAME: UI_NAME + _BUILD_UI_NAME: UI_NAME, } = setupDotenvFilesForEnv({ env: process.env.NODE_ENV }); if (OUTPUT_ONLY !== true) { console.info( - `\nPrepping files...\n\tSRC DIR: ${SRC_DIR}\n\tOUTPUT DIR: ${DIST_DIR}\n\tPUBLIC PATH: ${PUBLIC_PATH}\n` + `\nPrepping files...\n\tSRC DIR: ${SRC_DIR}\n\tOUTPUT DIR: ${DIST_DIR}\n\tPUBLIC PATH: ${PUBLIC_PATH}\n`, ); } @@ -31,13 +31,13 @@ rimrafSync(DIST_DIR); module.exports = () => ({ entry: { - app: path.join(SRC_DIR, 'index.tsx') + app: path.join(SRC_DIR, 'index.tsx'), }, output: { filename: '[name].bundle.js', path: DIST_DIR, publicPath: PUBLIC_PATH, - clean: true + clean: true, }, module: { rules: [ @@ -55,69 +55,69 @@ module.exports = () => ({ }, { test: /\.(svg|ttf|eot|woff|woff2)$/, - include: input => input.indexOf('fonts') > -1 || input.indexOf('pficon') > -1, + include: (input) => input.indexOf('fonts') > -1 || input.indexOf('pficon') > -1, type: 'asset/resource', generator: { - filename: 'fonts/[hash][ext][query]' - } + filename: 'fonts/[hash][ext][query]', + }, }, { test: /\.svg$/i, - include: input => input.indexOf('fonts') === -1 || input.indexOf('pficon') === -1, + include: (input) => input.indexOf('fonts') === -1 || input.indexOf('pficon') === -1, type: 'asset', parser: { - dataUrlCondition: { maxSize: 5000 } + dataUrlCondition: { maxSize: 5000 }, }, generator: { - dataUrl: content => svgToMiniDataURI(content.toString()), - filename: 'images/[hash][ext][query]' - } + dataUrl: (content) => svgToMiniDataURI(content.toString()), + filename: 'images/[hash][ext][query]', + }, }, { test: /\.(jpg|jpeg|png|gif)$/i, type: 'asset', parser: { - dataUrlCondition: { maxSize: 5000 } + dataUrlCondition: { maxSize: 5000 }, }, generator: { - filename: 'images/[hash][ext][query]' - } + filename: 'images/[hash][ext][query]', + }, }, { test: /\.(sa|sc|c)ss$/i, - use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] - } - ] + use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], + }, + ], }, plugins: [ ...setupWebpackDotenvFilesForEnv({ - directory: RELATIVE_DIRNAME + directory: RELATIVE_DIRNAME, }), new HtmlWebpackPlugin({ ...(UI_NAME && { title: UI_NAME }), - template: path.join(STATIC_DIR, 'index.html') + template: path.join(STATIC_DIR, 'index.html'), }), new HtmlReplaceWebpackPlugin([ { pattern: /%([A-Z_]+)%/g, - replacement: (match, $1) => process.env?.[$1] || match - } + replacement: (match, $1) => process.env?.[$1] || match, + }, ]), ...(() => { try { const fileResults = fs .readdirSync(STATIC_DIR) - ?.filter(fileDir => !/^(\.|index)/.test(fileDir)) - ?.map(fileDir => ({ + ?.filter((fileDir) => !/^(\.|index)/.test(fileDir)) + ?.map((fileDir) => ({ from: path.join(STATIC_DIR, fileDir), - to: path.join(DIST_DIR, fileDir) + to: path.join(DIST_DIR, fileDir), })); return ( (fileResults?.length > 0 && [ new CopyPlugin({ - patterns: fileResults - }) + patterns: fileResults, + }), ]) || [] ); @@ -125,7 +125,7 @@ module.exports = () => ({ console.error(`./config/webpack.common.js copy plugin error: ${e.message}`); return []; } - })() + })(), ], resolve: { extensions: ['.js', '.ts', '.tsx', '.jsx'], @@ -135,6 +135,6 @@ module.exports = () => ({ }), ], symlinks: false, - cacheWithContext: false - } + cacheWithContext: false, + }, }); diff --git a/config/webpack.dev.js b/config/webpack.dev.js index 3a1401c85..52800591f 100644 --- a/config/webpack.dev.js +++ b/config/webpack.dev.js @@ -10,7 +10,7 @@ const { _BUILD_OPEN_PATH: OPEN_PATH, _BUILD_RELATIVE_DIRNAME: RELATIVE_DIRNAME, _BUILD_PORT: PORT, - _BUILD_SRC: SRC_DIR + _BUILD_SRC: SRC_DIR, } = setupDotenvFilesForEnv({ env: process.env.NODE_ENV }); const webpackCommon = require('./webpack.common'); @@ -19,13 +19,13 @@ module.exports = merge( plugins: [ ...setupWebpackDotenvFilesForEnv({ directory: RELATIVE_DIRNAME, - env: MODE - }) + env: MODE, + }), // new ESLintPlugin({ // context: SRC_DIR, // failOnError: false // }) - ] + ], }, webpackCommon(), { @@ -40,23 +40,23 @@ module.exports = merge( hot: true, devMiddleware: { stats: 'errors-only', - writeToDisk: false + writeToDisk: false, }, client: { overlay: false, - progress: false + progress: false, }, static: { - directory: DIST_DIR + directory: DIST_DIR, }, watchFiles: { - paths: ['src/**/*', 'public/**/*'] - } + paths: ['src/**/*', 'public/**/*'], + }, }, plugins: [ new MiniCssExtractPlugin({ - filename: '[name].bundle.css' - }) - ] - } + filename: '[name].bundle.css', + }), + ], + }, ); diff --git a/config/webpack.prod.js b/config/webpack.prod.js index ba1fc83af..adf4795cf 100644 --- a/config/webpack.prod.js +++ b/config/webpack.prod.js @@ -5,7 +5,7 @@ const TerserJSPlugin = require('terser-webpack-plugin'); const { merge } = require('webpack-merge'); const { setupWebpackDotenvFilesForEnv, setupDotenvFilesForEnv } = require('./build.dotenv'); const { NODE_ENV: MODE, _BUILD_RELATIVE_DIRNAME: RELATIVE_DIRNAME } = setupDotenvFilesForEnv({ - env: process.env.NODE_ENV + env: process.env.NODE_ENV, }); const webpackCommon = require('./webpack.common'); @@ -14,9 +14,9 @@ module.exports = merge( plugins: [ ...setupWebpackDotenvFilesForEnv({ directory: RELATIVE_DIRNAME, - env: MODE - }) - ] + env: MODE, + }), + ], }, webpackCommon(), { @@ -24,19 +24,19 @@ module.exports = merge( devtool: undefined, output: { chunkFilename: '[name].[contenthash:8].chunk.js', - filename: '[name].[contenthash:8].js' + filename: '[name].[contenthash:8].js', }, optimization: { minimize: true, minimizer: [ new TerserJSPlugin({ - parallel: true + parallel: true, }), new CssMinimizerPlugin({ minimizerOptions: { - preset: ['default', { mergeLonghand: false }] - } - }) + preset: ['default', { mergeLonghand: false }], + }, + }), ], runtimeChunk: 'single', splitChunks: { @@ -45,16 +45,16 @@ module.exports = merge( vendor: { chunks: 'all', name: 'vendor', - test: /[\\/]node_modules[\\/]/ - } - } - } + test: /[\\/]node_modules[\\/]/, + }, + }, + }, }, plugins: [ new MiniCssExtractPlugin({ chunkFilename: '[name].[contenthash:8].chunk.css', - filename: '[name].[contenthash:8].css' - }) - ] - } + filename: '[name].[contenthash:8].css', + }), + ], + }, ); diff --git a/config/webpack.stage.js b/config/webpack.stage.js index b52858156..b9fbb6f5f 100644 --- a/config/webpack.stage.js +++ b/config/webpack.stage.js @@ -9,7 +9,7 @@ const { _BUILD_HOST: HOST, _BUILD_RELATIVE_DIRNAME: RELATIVE_DIRNAME, _BUILD_PORT: PORT, - _BUILD_SRC: SRC_DIR + _BUILD_SRC: SRC_DIR, } = setupDotenvFilesForEnv({ env: 'staging' }); const webpackCommon = require('./webpack.common'); @@ -18,13 +18,13 @@ module.exports = merge( plugins: [ ...setupWebpackDotenvFilesForEnv({ directory: RELATIVE_DIRNAME, - env: MODE + env: MODE, }), new ESLintPlugin({ context: SRC_DIR, - failOnError: false - }) - ] + failOnError: false, + }), + ], }, webpackCommon(), { @@ -32,8 +32,8 @@ module.exports = merge( devtool: 'eval-source-map', plugins: [ new MiniCssExtractPlugin({ - filename: '[name].bundle.css' - }) + filename: '[name].bundle.css', + }), ], devServer: { host: HOST, @@ -43,18 +43,18 @@ module.exports = merge( hot: true, devMiddleware: { stats: 'errors-only', - writeToDisk: true + writeToDisk: true, }, client: { overlay: false, - progress: false + progress: false, }, static: { - directory: DIST_DIR + directory: DIST_DIR, }, watchFiles: { - paths: ['src/**/*', 'public/**/*'] - } - } - } + paths: ['src/**/*', 'public/**/*'], + }, + }, + }, ); diff --git a/jest.config.js b/jest.config.js index d9df9400d..36f139f53 100644 --- a/jest.config.js +++ b/jest.config.js @@ -19,12 +19,12 @@ module.exports = { '\\.(css|less)$': '/__mocks__/styleMock.js', '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '/__mocks__/fileMock.js', - '@app/(.*)': '/src/app/$1' + '@app/(.*)': '/src/app/$1', }, // A preset that is used as a base for Jest's configuration preset: 'ts-jest/presets/js-with-ts', // The test environment that will be used for testing. - testEnvironment: 'jsdom' + testEnvironment: 'jsdom', }; diff --git a/package.json b/package.json index 57898727f..17ba6ef6b 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "test:coverage": "jest --coverage", "eslint": "eslint --ext .tsx,.js ./src/", "lint": "npm run eslint", - "format": "prettier --check --write ./src/**/*.{tsx,ts}", + "format": "prettier --check --write .", "type-check": "tsc --noEmit", "ci-checks": "npm run type-check && npm run lint && npm run test:coverage", "build:bundle-profile": "webpack --config ./config/webpack.prod.js --profile --json > stats.json", diff --git a/public/index.html b/public/index.html index e0a7928eb..961ba9a6c 100644 --- a/public/index.html +++ b/public/index.html @@ -1,17 +1,15 @@ - + - - - - - + + + + + %REACT_APP_UI_NAME% - +
diff --git a/scripts/actions.commit.js b/scripts/actions.commit.js index 6ba44d9f3..2f242c562 100644 --- a/scripts/actions.commit.js +++ b/scripts/actions.commit.js @@ -4,14 +4,14 @@ * @param {string} commits * @returns {{issueNumber: string, description: string, trimmedMessage: string, hash: string, typeScope: string}[]} */ -const messages = commits => +const messages = (commits) => commits .trim() .replace(/\n/g, '') .replace(/\+\s/g, '\n') .replace(/\n/, '') .split(/\n/g) - .map(message => { + .map((message) => { const [hashTypeScope, ...issueNumberDescription] = (/:/.test(message) && message.split(/:/)) || message.split(/\s/); @@ -20,9 +20,8 @@ const messages = commits => const updatedTypeScope = (typeScope && `${typeScope}:`) || ''; const updatedDescription = description.join(' '); - const [updatedMessage, remainingMessage = ''] = `${updatedTypeScope} ${issueNumber} ${updatedDescription}`.split( - /\(#\d{1,5}\)/ - ); + const [updatedMessage, remainingMessage = ''] = + `${updatedTypeScope} ${issueNumber} ${updatedDescription}`.split(/\(#\d{1,5}\)/); return { trimmedMessage: @@ -31,7 +30,7 @@ const messages = commits => hash, typeScope: updatedTypeScope, issueNumber, - description: updatedDescription + description: updatedDescription, }; }); @@ -48,18 +47,29 @@ const messages = commits => * do not count against this limit. * @returns {Array} */ -const messagesList = (parsedMessages, { issueNumberExceptions = false, maxMessageLength = 65 } = {}) => - parsedMessages.map(message => { - const { trimmedMessage = null, typeScope = null, issueNumber = null, description = null } = message; +const messagesList = ( + parsedMessages, + { issueNumberExceptions = false, maxMessageLength = 65 } = {}, +) => + parsedMessages.map((message) => { + const { + trimmedMessage = null, + typeScope = null, + issueNumber = null, + description = null, + } = message; const issueNumberRegex = `(^{0}\\([\\d\\D]+\\))`; const issueNumberException = !issueNumberExceptions ? true : new RegExp( - `${issueNumberExceptions.map(issueType => issueNumberRegex.replace('{0}', issueType)).join('|')}` + `${issueNumberExceptions + .map((issueType) => issueNumberRegex.replace('{0}', issueType)) + .join('|')}`, ).test(typeScope) || /\(#[\d\D]+\)$/.test(description); - const typeScopeValid = (/(^[\d\D]+\([\d\D]+\):$)|(^[\d\D]+:$)/.test(typeScope) && 'valid') || 'INVALID: type scope'; + const typeScopeValid = + (/(^[\d\D]+\([\d\D]+\):$)|(^[\d\D]+:$)/.test(typeScope) && 'valid') || 'INVALID: type scope'; const issueNumberValid = (/(^issues\/[\d,]+$)/.test(issueNumber) && 'valid') || @@ -85,8 +95,8 @@ const messagesList = (parsedMessages, { issueNumberExceptions = false, maxMessag * @param {Array} parsedMessagesList * @returns {Array} */ -const filteredMessages = parsedMessagesList => - parsedMessagesList.filter(value => !/[\d\D]*[\d\D]*/.test(value)); +const filteredMessages = (parsedMessagesList) => + parsedMessagesList.filter((value) => !/[\d\D]*[\d\D]*/.test(value)); /** * If commits exist, lint them. @@ -94,7 +104,7 @@ const filteredMessages = parsedMessagesList => * @param {string} commits * @returns {{resultsArray: Array, resultsString: string}} */ -module.exports = commits => { +module.exports = (commits) => { const lintResults = { resultsArray: [], resultsString: '' }; if (commits) { diff --git a/scripts/quipudocs.js b/scripts/quipudocs.js index 53223cae8..a2d529e92 100644 --- a/scripts/quipudocs.js +++ b/scripts/quipudocs.js @@ -18,7 +18,7 @@ const buildEa = () => { fs.writeFileSync(fileOutput, JSON.stringify(_merge(currentFileOutput, localesJSON), null, 2)); - Object.keys(eaJSON).forEach(key => { + Object.keys(eaJSON).forEach((key) => { const langFile = `${dir}${key}.json`; let currentLangFile = {}; diff --git a/src/app/app.test.tsx b/src/app/app.test.tsx index 772b5f88d..c6f764dcd 100644 --- a/src/app/app.test.tsx +++ b/src/app/app.test.tsx @@ -8,7 +8,7 @@ it('renders without crashing', () => { root.render( - + , ); root.unmount(); }); diff --git a/src/app/appLayout/AppLayout.tsx b/src/app/appLayout/AppLayout.tsx index 0b1f5aeac..6ba0d6e78 100644 --- a/src/app/appLayout/AppLayout.tsx +++ b/src/app/appLayout/AppLayout.tsx @@ -15,7 +15,7 @@ import { Page, PageSidebar, PageSidebarBody, - SkipToContent + SkipToContent, } from '@patternfly/react-core'; import { BarsIcon } from '@patternfly/react-icons'; import logo from '../bgimages/title.svg'; @@ -67,7 +67,7 @@ const AppLayout: React.FunctionComponent = ({ children }) => { key={`${group.label}-${groupIndex}`} id={`${group.label}-${groupIndex}`} title={group.label} - isActive={group.routes.some(route => route.path === location.pathname)} + isActive={group.routes.some((route) => route.path === location.pathname)} > {group.routes.map((route, idx) => route.label && renderNavItem(route, idx))} @@ -78,7 +78,7 @@ const AppLayout: React.FunctionComponent = ({ children }) => { {routes.map( (route, idx) => - route.label && (!route.routes ? renderNavItem(route, idx) : renderNavGroup(route, idx)) + route.label && (!route.routes ? renderNavItem(route, idx) : renderNavGroup(route, idx)), )} @@ -94,7 +94,7 @@ const AppLayout: React.FunctionComponent = ({ children }) => { const PageSkipToContent = ( { + onClick={(event) => { event.preventDefault(); const primaryContentContainer = document.getElementById(pageId); if (primaryContentContainer) { diff --git a/src/app/appLayout/AppToolbar.tsx b/src/app/appLayout/AppToolbar.tsx index 5b64d08df..ae7e1009f 100644 --- a/src/app/appLayout/AppToolbar.tsx +++ b/src/app/appLayout/AppToolbar.tsx @@ -6,7 +6,7 @@ import { Toolbar, ToolbarContent, ToolbarGroup, - ToolbarItem + ToolbarItem, } from '@patternfly/react-core'; import { EllipsisVIcon, QuestionCircleIcon } from '@patternfly/react-icons'; import { useUsername } from '../../components/sessionContext/SessionProvider'; @@ -26,7 +26,7 @@ const AppToolbar: React.FunctionComponent = () => { const onHelpSelect = ( _event: React.MouseEvent | undefined, - value: string | number | undefined + value: string | number | undefined, ) => { // eslint-disable-next-line no-console console.log('selected', value); @@ -35,7 +35,7 @@ const AppToolbar: React.FunctionComponent = () => { const onUserDropdownSelect = ( _event: React.MouseEvent | undefined, - value: string | number | undefined + value: string | number | undefined, ) => { // eslint-disable-next-line no-console console.log('selected', value); @@ -60,12 +60,12 @@ const AppToolbar: React.FunctionComponent = () => { onSelect={onHelpSelect} onOpenChange={(isOpen: boolean) => setHelpOpen(isOpen)} isOpen={helpOpen} - toggle={toggleRef => ( + toggle={(toggleRef) => ( setHelpOpen(prev => !prev)} + onClick={() => setHelpOpen((prev) => !prev)} isExpanded={helpOpen} > @@ -85,12 +85,12 @@ const AppToolbar: React.FunctionComponent = () => { onSelect={onUserDropdownSelect} onOpenChange={(isOpen: boolean) => setKebabDropdownOpen(isOpen)} isOpen={kebabDropdownOpen} - toggle={toggleRef => ( + toggle={(toggleRef) => ( setKebabDropdownOpen(prev => !prev)} + onClick={() => setKebabDropdownOpen((prev) => !prev)} isExpanded={kebabDropdownOpen} style={{ width: 'auto' }} > @@ -111,12 +111,12 @@ const AppToolbar: React.FunctionComponent = () => { onOpenChange={(isOpen: boolean) => setUserDropdownOpen(isOpen)} isOpen={userDropdownOpen} ouiaId="user_dropdown" - toggle={toggleRef => ( + toggle={(toggleRef) => ( setUserDropdownOpen(prev => !prev)} + onClick={() => setUserDropdownOpen((prev) => !prev)} isExpanded={userDropdownOpen} >
diff --git a/src/app/routes.tsx b/src/app/routes.tsx index fd630f151..0559595bd 100644 --- a/src/app/routes.tsx +++ b/src/app/routes.tsx @@ -5,7 +5,7 @@ import { Navigate, Redirect } from 'react-router-dom'; const Sources = React.lazy(() => import('../pages/sources/SourcesListView')); const Scans = React.lazy(() => import('../pages/scans/ScansListView')); -const Credentials = React.lazy(() => import('../pages/credentials/CredentialsListView')) +const Credentials = React.lazy(() => import('../pages/credentials/CredentialsListView')); export interface IAppRoute { id: string; @@ -30,33 +30,33 @@ const routes: AppRouteConfig[] = [ component: , label: 'Sources', path: '/sources', - title: 'Sources' + title: 'Sources', }, { id: 'scans', component: , label: 'Scans', path: '/scans', - title: 'Scans' + title: 'Scans', }, { id: 'credentials', component: , label: 'Credentials', path: '/credentials', - title: 'Credentials' - } + title: 'Credentials', + }, ]; const flattenedRoutes: IAppRoute[] = routes.reduce( (flattened, route) => [...flattened, ...(route.routes ? route.routes : [route])], - [] as IAppRoute[] + [] as IAppRoute[], ); const AppRoutes = (): React.ReactElement => ( Loading...

}> - {flattenedRoutes.map(route => ( + {flattenedRoutes.map((route) => ( ))} } /> diff --git a/src/common/helpers.ts b/src/common/helpers.ts index 960758176..562529105 100644 --- a/src/common/helpers.ts +++ b/src/common/helpers.ts @@ -19,7 +19,7 @@ const aggregatedError = (errors: any, message: any, { name = 'AggregateError' } return err; }; -const copyClipboard = text => { +const copyClipboard = (text) => { let successful; const win = window as any; @@ -89,12 +89,14 @@ const downloadData = (data = '', fileName = 'download.txt', fileType = 'text/pla }); const generateId = (prefix: string): string => - `${prefix || 'generatedid'}-${(process.env.REACT_APP_ENV !== 'test' && Math.ceil(1e5 * Math.random())) || ''}`; + `${prefix || 'generatedid'}-${ + (process.env.REACT_APP_ENV !== 'test' && Math.ceil(1e5 * Math.random())) || '' + }`; const noopTranslate = ( key: string | string[], value: string | string[], - components: readonly React.ReactElement[] | { readonly [tagName: string]: React.ReactElement } + components: readonly React.ReactElement[] | { readonly [tagName: string]: React.ReactElement }, ): string => { const updatedKey = (Array.isArray(key) && `[${key}]`) || key; const updatedValue = @@ -112,11 +114,12 @@ const noopTranslate = ( const setPropIfDefined = (obj: any, props: PropertyPath, value: any) => obj && value !== undefined ? _set(obj, props, value) : obj; -const setPropIfTruthy = (obj: any, props: PropertyPath, value: any) => (obj && value ? _set(obj, props, value) : obj); +const setPropIfTruthy = (obj: any, props: PropertyPath, value: any) => + obj && value ? _set(obj, props, value) : obj; const getMessageFromResults = ( results: { status: any; statusText: string; message: string; detail: any }, - filter = null + filter = null, ) => { const status: number = _get(results, 'response.status', results.status); const statusResponse: string = _get(results, 'response.statusText', results.statusText); @@ -128,7 +131,7 @@ const getMessageFromResults = ( messages: { message: '' }, message: '', status: status || 0, - url: requestUrl + url: requestUrl, }; const displayStatus = status >= 500 ? `${status} ` : ''; @@ -165,7 +168,7 @@ const getMessageFromResults = ( return messages; } - const getMessages = messageObjectArrayString => { + const getMessages = (messageObjectArrayString) => { const parsed = {}; if (messageObjectArrayString && typeof messageObjectArrayString === 'string') { @@ -176,7 +179,7 @@ const getMessageFromResults = ( return getMessages(messageObjectArrayString.join('\n')); } - Object.keys(messageObjectArrayString).forEach(key => { + Object.keys(messageObjectArrayString).forEach((key) => { parsed[key] = getMessages(messageObjectArrayString[key]); }); @@ -186,9 +189,10 @@ const getMessageFromResults = ( const filtered = (messageObjectArrayString, filterField) => { const parsed = {}; const str = JSON.stringify(messageObjectArrayString); - const filterFields = (Array.isArray(filterField) && filterField) || (filterField && [filterField]) || []; + const filterFields = + (Array.isArray(filterField) && filterField) || (filterField && [filterField]) || []; - filterFields.forEach(val => { + filterFields.forEach((val) => { const match = str.match(new RegExp(`"${val}":(\\[(.*?)]]?|{(.*?)}]?|"(.*?)"),?`)); if (match && match[1]) { @@ -212,7 +216,8 @@ const getMessageFromResults = ( }; messages.messages = - (filter && filtered(messageResponse || detailResponse, filter)) || getMessages(messageResponse || detailResponse); + (filter && filtered(messageResponse || detailResponse, filter)) || + getMessages(messageResponse || detailResponse); messages.message = `${displayStatus}${Object.values(messages.messages).join('\n')}`; if (messages.message === '[object Object]') { @@ -223,7 +228,7 @@ const getMessageFromResults = ( return messages; }; -const getStatusFromResults = results => { +const getStatusFromResults = (results) => { let status = _get(results, 'response.status', results.status); if (status === undefined) { @@ -235,18 +240,18 @@ const getStatusFromResults = results => { const getTimeStampFromResults = process.env.REACT_APP_ENV !== 'test' - ? results => moment(_get(results, 'headers.date', Date.now())).format('YYYYMMDD_HHmmss') + ? (results) => moment(_get(results, 'headers.date', Date.now())).format('YYYYMMDD_HHmmss') : () => '20190225_164640'; const getTimeDisplayHowLongAgo = process.env.REACT_APP_ENV !== 'test' - ? timestamp => moment.utc(timestamp).utcOffset(moment().utcOffset()).fromNow() + ? (timestamp) => moment.utc(timestamp).utcOffset(moment().utcOffset()).fromNow() : () => 'a day ago'; const isIpAddress = (name: string): boolean => { const vals = name.split('.'); if (vals.length === 4) { - return vals.find(val => Number.isNaN(val)) === undefined; + return vals.find((val) => Number.isNaN(val)) === undefined; } return false; }; @@ -275,7 +280,9 @@ const UI_SENTENCE_START_NAME = UI_BRAND ? process.env.REACT_APP_UI_BRAND_SENTENCE_START_NAME : process.env.REACT_APP_UI_SENTENCE_START_NAME; -const UI_SHORT_NAME = UI_BRAND ? process.env.REACT_APP_UI_BRAND_SHORT_NAME : process.env.REACT_APP_UI_SHORT_NAME; +const UI_SHORT_NAME = UI_BRAND + ? process.env.REACT_APP_UI_BRAND_SHORT_NAME + : process.env.REACT_APP_UI_SHORT_NAME; const UI_VERSION = process.env.REACT_APP_UI_VERSION; @@ -285,9 +292,12 @@ const TOAST_NOTIFICATIONS_TIMEOUT = undefined; const POLL_INTERVAL = - (process.env.REACT_APP_POLL_INTERVAL && Number.parseInt(process.env.REACT_APP_POLL_INTERVAL, 10)) || undefined; + (process.env.REACT_APP_POLL_INTERVAL && + Number.parseInt(process.env.REACT_APP_POLL_INTERVAL, 10)) || + undefined; -const getCurrentDate = () => (TEST_MODE && moment.utc('20220601').toDate()) || moment.utc().toDate(); +const getCurrentDate = () => + (TEST_MODE && moment.utc('20220601').toDate()) || moment.utc().toDate(); const helpers = { aggregatedError, @@ -314,7 +324,7 @@ const helpers = { UI_SENTENCE_START_NAME, UI_SHORT_NAME, UI_VERSION, - getCurrentDate + getCurrentDate, }; export { helpers as default, helpers }; diff --git a/src/components/SimpleDropdown.tsx b/src/components/SimpleDropdown.tsx index b107a0f0f..f2a196669 100644 --- a/src/components/SimpleDropdown.tsx +++ b/src/components/SimpleDropdown.tsx @@ -1,51 +1,46 @@ -import React, { useState } from "react"; +import React, { useState } from 'react'; -import { - Dropdown, - DropdownList, - MenuToggle, - MenuToggleElement, -} from "@patternfly/react-core"; +import { Dropdown, DropdownList, MenuToggle, MenuToggleElement } from '@patternfly/react-core'; export interface ISimpleDropdownProps { - label: string; - dropdownItems?: React.ReactNode[]; - ariaLabel?: string; - onSelect?: () => {}; - variant: 'default' | 'plain' | 'primary' | 'secondary'; - isFullWidth?: boolean; + label: string; + dropdownItems?: React.ReactNode[]; + ariaLabel?: string; + onSelect?: () => {}; + variant: 'default' | 'plain' | 'primary' | 'secondary'; + isFullWidth?: boolean; } export const SimpleDropdown: React.FC = ({ - label, - dropdownItems, - ariaLabel, - onSelect, - variant, - isFullWidth + label, + dropdownItems, + ariaLabel, + onSelect, + variant, + isFullWidth, }) => { - const [isOpen, setIsOpen] = useState(false); + const [isOpen, setIsOpen] = useState(false); - return ( - setIsOpen(isOpen)} - onSelect={onSelect} - toggle={(toggleRef: React.Ref) => ( - setIsOpen(!isOpen)} - variant={variant} - aria-label={ariaLabel || "Dropdown menu"} - isDisabled={!dropdownItems || dropdownItems.length === 0} - > - {label} - - )} + return ( + setIsOpen(isOpen)} + onSelect={onSelect} + toggle={(toggleRef: React.Ref) => ( + setIsOpen(!isOpen)} + variant={variant} + aria-label={ariaLabel || 'Dropdown menu'} + isDisabled={!dropdownItems || dropdownItems.length === 0} > - {dropdownItems} - - ); + {label} + + )} + > + {dropdownItems} + + ); }; diff --git a/src/components/TypeaheadCheckboxes.tsx b/src/components/TypeaheadCheckboxes.tsx index 3d1b6b5f9..5bef0735a 100644 --- a/src/components/TypeaheadCheckboxes.tsx +++ b/src/components/TypeaheadCheckboxes.tsx @@ -1,209 +1,223 @@ import React from 'react'; import { - Select, - SelectOption, - SelectList, - SelectOptionProps, - MenuToggle, - MenuToggleElement, - TextInputGroup, - TextInputGroupMain, - TextInputGroupUtilities, - Button + Select, + SelectOption, + SelectList, + SelectOptionProps, + MenuToggle, + MenuToggleElement, + TextInputGroup, + TextInputGroupMain, + TextInputGroupUtilities, + Button, } from '@patternfly/react-core'; import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; export interface ITypeaheadCheckboxesProps { - onChange: (selections: string[]) => void; - options: { value: string, label: string }[]; - selectedOptions?: string[]; - placeholder?: string + onChange: (selections: string[]) => void; + options: { value: string; label: string }[]; + selectedOptions?: string[]; + placeholder?: string; } export const TypeaheadCheckboxes: React.FC = ({ - onChange, - options, - selectedOptions = [], - placeholder = '0 items selected', + onChange, + options, + selectedOptions = [], + placeholder = '0 items selected', }) => { - const [isOpen, setIsOpen] = React.useState(false); - const [inputValue, setInputValue] = React.useState(''); - const [selected, setSelected] = React.useState(selectedOptions || []); - const [selectOptions, setSelectOptions] = React.useState(options); - const [focusedItemIndex, setFocusedItemIndex] = React.useState(null); - const [activeItem, setActiveItem] = React.useState(null); - const [activePlaceholder, setActivePlaceholder] = React.useState(placeholder); - const textInputRef = React.useRef(); - - React.useEffect(() => { - setSelectOptions(options); - }, [options]); - - React.useEffect(() => { - let newSelectOptions: SelectOptionProps[] = options; - - // Filter menu items based on the text input value when one exists - if (inputValue) { - newSelectOptions = options.filter((menuItem) => - String(menuItem.label).toLowerCase().includes(inputValue.toLowerCase()) - ); - - // When no options are found after filtering, display 'No results found' - if (!newSelectOptions.length) { - newSelectOptions = [ - { isDisabled: false, children: `No results found for "${inputValue}"`, value: 'no results' } - ]; - } - - // Open the menu when the input value changes and the new value is not empty - if (!isOpen) { - setIsOpen(true); - } + const [isOpen, setIsOpen] = React.useState(false); + const [inputValue, setInputValue] = React.useState(''); + const [selected, setSelected] = React.useState(selectedOptions || []); + const [selectOptions, setSelectOptions] = React.useState(options); + const [focusedItemIndex, setFocusedItemIndex] = React.useState(null); + const [activeItem, setActiveItem] = React.useState(null); + const [activePlaceholder, setActivePlaceholder] = React.useState(placeholder); + const textInputRef = React.useRef(); + + React.useEffect(() => { + setSelectOptions(options); + }, [options]); + + React.useEffect(() => { + let newSelectOptions: SelectOptionProps[] = options; + + // Filter menu items based on the text input value when one exists + if (inputValue) { + newSelectOptions = options.filter((menuItem) => + String(menuItem.label).toLowerCase().includes(inputValue.toLowerCase()), + ); + + // When no options are found after filtering, display 'No results found' + if (!newSelectOptions.length) { + newSelectOptions = [ + { + isDisabled: false, + children: `No results found for "${inputValue}"`, + value: 'no results', + }, + ]; + } + + // Open the menu when the input value changes and the new value is not empty + if (!isOpen) { + setIsOpen(true); + } + } + + setSelectOptions(newSelectOptions); + setFocusedItemIndex(null); + setActiveItem(null); + }, [inputValue]); + + const handleMenuArrowKeys = (key: string) => { + let indexToFocus; + + if (isOpen) { + if (key === 'ArrowUp') { + // When no index is set or at the first index, focus to the last, otherwise decrement focus index + if (focusedItemIndex === null || focusedItemIndex === 0) { + indexToFocus = selectOptions.length - 1; + } else { + indexToFocus = focusedItemIndex - 1; } - - setSelectOptions(newSelectOptions); - setFocusedItemIndex(null); - setActiveItem(null); - }, [inputValue]); - - const handleMenuArrowKeys = (key: string) => { - let indexToFocus; - - if (isOpen) { - if (key === 'ArrowUp') { - // When no index is set or at the first index, focus to the last, otherwise decrement focus index - if (focusedItemIndex === null || focusedItemIndex === 0) { - indexToFocus = selectOptions.length - 1; - } else { - indexToFocus = focusedItemIndex - 1; - } - } - - if (key === 'ArrowDown') { - // When no index is set or at the last index, focus to the first, otherwise increment focus index - if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) { - indexToFocus = 0; - } else { - indexToFocus = focusedItemIndex + 1; - } - } - - setFocusedItemIndex(indexToFocus); - const focusedItem = selectOptions.filter((option) => !option.isDisabled)[indexToFocus]; - setActiveItem(`select-multi-typeahead-checkbox-${String(focusedItem.value).replace(' ', '-')}`); + } + + if (key === 'ArrowDown') { + // When no index is set or at the last index, focus to the first, otherwise increment focus index + if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) { + indexToFocus = 0; + } else { + indexToFocus = focusedItemIndex + 1; } - }; - - const onInputKeyDown = (event: React.KeyboardEvent) => { - const enabledMenuItems = selectOptions.filter((menuItem) => !menuItem.isDisabled); - const [firstMenuItem] = enabledMenuItems; - const focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem; - - switch (event.key) { - // Select the first available option - case 'Enter': - if (!isOpen) { - setIsOpen((prevIsOpen) => !prevIsOpen); - } else if (isOpen && focusedItem.value !== 'no results') { - onSelect(focusedItem.value as string); - } - break; - case 'Tab': - case 'Escape': - setIsOpen(false); - setActiveItem(null); - break; - case 'ArrowUp': - case 'ArrowDown': - event.preventDefault(); - handleMenuArrowKeys(event.key); - break; - } - }; - - const onToggleClick = () => { - setIsOpen(!isOpen); - }; - - const onTextInputChange = (_event: React.FormEvent, value: string) => { - setInputValue(value); - }; - - const onSelect = (value: string) => { - if (value && value !== 'no results') { - const newSelected = selected.includes(value) ? selected.filter((selection) => selection !== value) : [...selected, value]; - onChange(newSelected); - setSelected(newSelected); + } + + setFocusedItemIndex(indexToFocus); + const focusedItem = selectOptions.filter((option) => !option.isDisabled)[indexToFocus]; + setActiveItem( + `select-multi-typeahead-checkbox-${String(focusedItem.value).replace(' ', '-')}`, + ); + } + }; + + const onInputKeyDown = (event: React.KeyboardEvent) => { + const enabledMenuItems = selectOptions.filter((menuItem) => !menuItem.isDisabled); + const [firstMenuItem] = enabledMenuItems; + const focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem; + + switch (event.key) { + // Select the first available option + case 'Enter': + if (!isOpen) { + setIsOpen((prevIsOpen) => !prevIsOpen); + } else if (isOpen && focusedItem.value !== 'no results') { + onSelect(focusedItem.value as string); } - - textInputRef.current?.focus(); - }; - - React.useEffect(() => { - setActivePlaceholder(selected.length ? `${selected.length} items selected` : placeholder); - }, [selected]); - - const toggle = (toggleRef: React.Ref) => ( - - - - - {selected.length > 0 && ( - - )} - - - - ); - - return ( - - ); + break; + case 'Tab': + case 'Escape': + setIsOpen(false); + setActiveItem(null); + break; + case 'ArrowUp': + case 'ArrowDown': + event.preventDefault(); + handleMenuArrowKeys(event.key); + break; + } + }; + + const onToggleClick = () => { + setIsOpen(!isOpen); + }; + + const onTextInputChange = (_event: React.FormEvent, value: string) => { + setInputValue(value); + }; + + const onSelect = (value: string) => { + if (value && value !== 'no results') { + const newSelected = selected.includes(value) + ? selected.filter((selection) => selection !== value) + : [...selected, value]; + onChange(newSelected); + setSelected(newSelected); + } + + textInputRef.current?.focus(); + }; + + React.useEffect(() => { + setActivePlaceholder(selected.length ? `${selected.length} items selected` : placeholder); + }, [selected]); + + const toggle = (toggleRef: React.Ref) => ( + + + + + {selected.length > 0 && ( + + )} + + + + ); + + return ( + + ); }; diff --git a/src/components/contextIcon/contextIcon.tsx b/src/components/contextIcon/contextIcon.tsx index c2c237140..17df253ac 100644 --- a/src/components/contextIcon/contextIcon.tsx +++ b/src/components/contextIcon/contextIcon.tsx @@ -19,13 +19,13 @@ import { PficonVcenterIcon, TrashIcon, UnknownIcon, - UserIcon + UserIcon, } from '@patternfly/react-icons'; import { global_Color_dark_100 as gray, global_success_color_100 as green, global_warning_color_100 as yellow, - global_danger_color_100 as red + global_danger_color_100 as red, } from '@patternfly/react-tokens'; /** @@ -48,7 +48,7 @@ const ContextIconColors: { gray, green, yellow, - red + red, }; const ContextIconVariant: { [key: string]: string } = { @@ -78,7 +78,7 @@ const ContextIconVariant: { [key: string]: string } = { user: 'user', vcenter: 'vcenter', ansible: 'ansible', - acs: 'acs' + acs: 'acs', }; const ContextIcon: React.FC<{ symbol: string; size?: 'sm' | 'md' | 'lg' | 'xl' }> = ({ diff --git a/src/components/contextIcon/contextIconAction.tsx b/src/components/contextIcon/contextIconAction.tsx index 089ff7edb..dd62b11eb 100644 --- a/src/components/contextIcon/contextIconAction.tsx +++ b/src/components/contextIcon/contextIconAction.tsx @@ -10,7 +10,7 @@ const ContextIconActionVariant = { created: 'running', running: 'running', paused: 'paused', - play: 'play' + play: 'play', }; const ContextIconAction: React.FC<{ symbol?: string }> = ({ symbol, ...props }) => { diff --git a/src/components/i18n/I18n.tsx b/src/components/i18n/I18n.tsx index d990c41a6..49e625ba5 100644 --- a/src/components/i18n/I18n.tsx +++ b/src/components/i18n/I18n.tsx @@ -16,7 +16,7 @@ const I18n: React.FunctionComponent = ({ fallbackLng = process.env.REACT_APP_CONFIG_SERVICE_LOCALES_DEFAULT_LNG, loadPath = process.env.REACT_APP_CONFIG_SERVICE_LOCALES_PATH, locale = null, - children + children, }) => { const [initialized, setInitialized] = useState(false); @@ -26,7 +26,7 @@ const I18n: React.FunctionComponent = ({ .use(initReactI18next) .init({ backend: { - loadPath + loadPath, }, fallbackLng, lng: undefined, @@ -34,8 +34,8 @@ const I18n: React.FunctionComponent = ({ ns: ['default'], defaultNS: 'default', react: { - useSuspense: false - } + useSuspense: false, + }, }) .then(() => { if (!canceled) { diff --git a/src/components/i18n/i18nHelpers.tsx b/src/components/i18n/i18nHelpers.tsx index 652ceaf20..5a00adfdc 100644 --- a/src/components/i18n/i18nHelpers.tsx +++ b/src/components/i18n/i18nHelpers.tsx @@ -13,21 +13,21 @@ const translate = ( components: | readonly React.ReactElement[] | { readonly [tagName: string]: React.ReactElement } = {}, - { emptyContextValue = EMPTY_CONTEXT } = {} + { emptyContextValue = EMPTY_CONTEXT } = {}, ): string | React.ReactNode => { const updatedValues = values || {}; let updatedTranslateKey = translateKey; if (Array.isArray(updatedTranslateKey)) { updatedTranslateKey = updatedTranslateKey.filter( - value => typeof value === 'string' && value.length > 0 + (value) => typeof value === 'string' && value.length > 0, ); } if (Array.isArray(updatedValues?.context)) { const updatedContext = updatedValues.context - .map(value => (value === emptyContextValue && ' ') || value) - .filter(value => typeof value === 'string' && value.length > 0); + .map((value) => (value === emptyContextValue && ' ') || value) + .filter((value) => typeof value === 'string' && value.length > 0); if (updatedContext?.length > 1) { const lastContext = updatedContext.pop(); diff --git a/src/components/refreshTimeButton/RefreshTimeButton.tsx b/src/components/refreshTimeButton/RefreshTimeButton.tsx index 6949b4b50..4d99f8148 100644 --- a/src/components/refreshTimeButton/RefreshTimeButton.tsx +++ b/src/components/refreshTimeButton/RefreshTimeButton.tsx @@ -12,7 +12,7 @@ type RefreshTimeButtonProps = { const RefreshTimeButton: React.FC = ({ lastRefresh = 0, onRefresh }) => { const { t } = useTranslation(); const [refresh, setRefresh] = React.useState( - lastRefresh ? helpers.getTimeDisplayHowLongAgo(lastRefresh) : null + lastRefresh ? helpers.getTimeDisplayHowLongAgo(lastRefresh) : null, ); const pollingInterval = React.useRef(); @@ -35,7 +35,7 @@ const RefreshTimeButton: React.FC = ({ lastRefresh = 0, {t('refresh-time-button.refreshed', { context: lastRefresh && 'load', - refresh: lastRefresh && refresh + refresh: lastRefresh && refresh, })} diff --git a/src/components/sessionContext/SessionProvider.tsx b/src/components/sessionContext/SessionProvider.tsx index b86db7e90..4db206dd2 100644 --- a/src/components/sessionContext/SessionProvider.tsx +++ b/src/components/sessionContext/SessionProvider.tsx @@ -18,7 +18,7 @@ const initialSessionData = { error: false, errorMessage: '', locale: null, - username: null + username: null, }; export const SessionContext = React.createContext({ ...initialSessionData }); @@ -28,7 +28,7 @@ export const useUsername = () => React.useContext(SessionContext).username; const getLocale = () => { const locale = { value: process.env.REACT_APP_CONFIG_SERVICE_LOCALES_DEFAULT_LNG, - key: process.env.REACT_APP_CONFIG_SERVICE_LOCALES_DEFAULT_LNG_DESC + key: process.env.REACT_APP_CONFIG_SERVICE_LOCALES_DEFAULT_LNG_DESC, }; return locale; }; @@ -38,19 +38,19 @@ const SessionProvider: React.FC<{ children: React.ReactNode }> = ({ children }) React.useEffect(() => { const fetchedLocale = getLocale(); - setSessionData(prev => ({ ...prev, locale: fetchedLocale.key })); + setSessionData((prev) => ({ ...prev, locale: fetchedLocale.key })); }, []); useQuery({ queryKey: [WHO_AM_I_QUERY], refetchOnWindowFocus: !helpers.DEV_MODE, queryFn: () => { - return axios.get(process.env.REACT_APP_USER_SERVICE_CURRENT || '').then(res => { + return axios.get(process.env.REACT_APP_USER_SERVICE_CURRENT || '').then((res) => { if (res.data.username) { - setSessionData(prev => ({ ...prev, authorized: true, username: res.data.username })); + setSessionData((prev) => ({ ...prev, authorized: true, username: res.data.username })); } }); - } + }, }); return {children}; diff --git a/src/constants/apiConstants.ts b/src/constants/apiConstants.ts index ad7bf75d1..590db1138 100644 --- a/src/constants/apiConstants.ts +++ b/src/constants/apiConstants.ts @@ -18,7 +18,7 @@ const API_QUERY_TYPES = { SOURCE_TYPE: 'source_type', SSH_KEYFILE: 'ssh_keyfile', SSH_PASSPHRASE: 'ssh_passphrase', - USERNAME: 'username' + USERNAME: 'username', }; const API_QUERY_SORT_TYPES = { @@ -26,7 +26,7 @@ const API_QUERY_SORT_TYPES = { MOST_RECENT_CONNECT_SCAN_START_TIME: 'most_recent_connect_scan__start_time', MOST_RECENT_SCANJOB_START_TIME: 'most_recent_scanjob__start_time', NAME: 'name', - SOURCE_TYPE: 'source_type' + SOURCE_TYPE: 'source_type', }; const API_QUERY_PAGE = 'page'; @@ -266,7 +266,7 @@ const apiTypes = { API_SUBMIT_SOURCE_OPTIONS_DISABLE_SSL, API_SUBMIT_SOURCE_OPTIONS_PARAMIKO, API_SUBMIT_SOURCE_PORT, - API_SUBMIT_SOURCE_SOURCE_TYPE + API_SUBMIT_SOURCE_SOURCE_TYPE, }; export { @@ -382,5 +382,5 @@ export { API_SUBMIT_SOURCE_OPTIONS_DISABLE_SSL, API_SUBMIT_SOURCE_OPTIONS_PARAMIKO, API_SUBMIT_SOURCE_PORT, - API_SUBMIT_SOURCE_SOURCE_TYPE + API_SUBMIT_SOURCE_SOURCE_TYPE, }; diff --git a/src/hooks/useSearchParam.ts b/src/hooks/useSearchParam.ts index 4560984c0..4616a3fb8 100644 --- a/src/hooks/useSearchParam.ts +++ b/src/hooks/useSearchParam.ts @@ -7,7 +7,7 @@ const useSearchParam = ( options?: { replace?: boolean; unsetWhenDefaultValue?: boolean; - } + }, // eslint-disable-next-line no-unused-vars ): [string | null, (newValue: string) => void, () => void] => { const defaultValueRef = React.useRef(defaultValue); @@ -27,7 +27,7 @@ const useSearchParam = ( setSearchParams(newSearchParams, { replace }); } }, - [name, setSearchParams, unsetWhenDefaultValue, replace] + [name, setSearchParams, unsetWhenDefaultValue, replace], ); const unset = React.useCallback(() => { diff --git a/src/index.html b/src/index.html index 8ed3a55ef..bb92abbca 100644 --- a/src/index.html +++ b/src/index.html @@ -1,18 +1,16 @@ - + + + + + + + + %REACT_APP_UI_NAME% + - - - - - - - %REACT_APP_UI_NAME% - - - - -
- - + + +
+ diff --git a/src/index.tsx b/src/index.tsx index 2bdfd8933..a23954eb7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import axios from 'axios'; -import { ReactQueryDevtools } from '@tanstack/react-query-devtools' +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import ReactDOM from 'react-dom/client'; import App from './app/App'; @@ -11,9 +11,9 @@ if (process.env.NODE_ENV !== 'production') { rules: [ { id: 'color-contrast', - enabled: false - } - ] + enabled: false, + }, + ], }; // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef,global-require const axe = require('react-axe'); @@ -24,19 +24,23 @@ const root = ReactDOM.createRoot(document.getElementById('root') as Element); const queryClient = new QueryClient(); //TODO: just to get token manually until we have login screen -axios.post('https://0.0.0.0:9443/api/v1/token/', { +axios + .post('https://0.0.0.0:9443/api/v1/token/', { username: 'admin', - password: 'pleasechangethispassword' - } -).then(res => { localStorage.setItem("authToken", res.data.token); console.log("Token", res.data.token)}); + password: 'pleasechangethispassword', + }) + .then((res) => { + localStorage.setItem('authToken', res.data.token); + console.log('Token', res.data.token); + }); root.render( - + {/* TODO: possibly add this back in when we do login/auth stuff */} - + {/* */} - + , ); diff --git a/src/pages/credentials/CredentialActionMenu.tsx b/src/pages/credentials/CredentialActionMenu.tsx index a69a48753..44fe45d02 100644 --- a/src/pages/credentials/CredentialActionMenu.tsx +++ b/src/pages/credentials/CredentialActionMenu.tsx @@ -4,7 +4,7 @@ import { DropdownItem, DropdownList, MenuToggle, - MenuToggleElement + MenuToggleElement, } from '@patternfly/react-core'; import { EllipsisVIcon } from '@patternfly/react-icons'; import { CredentialType } from '../../types'; @@ -40,7 +40,7 @@ const CredentialActionMenu: React.FC = ({ credential ref={toggleRef} aria-label="source actions" variant="plain" - onClick={() => setIsOpen(prev => !prev)} + onClick={() => setIsOpen((prev) => !prev)} isExpanded={isOpen} > @@ -60,4 +60,4 @@ const CredentialActionMenu: React.FC = ({ credential ); }; -export default CredentialActionMenu; \ No newline at end of file +export default CredentialActionMenu; diff --git a/src/pages/credentials/CredentialsListView.tsx b/src/pages/credentials/CredentialsListView.tsx index 7187c6311..d187f09f0 100644 --- a/src/pages/credentials/CredentialsListView.tsx +++ b/src/pages/credentials/CredentialsListView.tsx @@ -11,7 +11,7 @@ import { TableHeaderContentWithBatteries, TableRowContentWithBatteries, useTablePropHelpers, - useTableState + useTableState, } from '@mturley-latest/react-table-batteries'; import { helpers } from '../../common'; import { @@ -29,7 +29,7 @@ import { Title, Toolbar, ToolbarContent, - ToolbarItem + ToolbarItem, } from '@patternfly/react-core'; import { RefreshTimeButton } from '../../components/refreshTimeButton/RefreshTimeButton'; import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; @@ -44,7 +44,7 @@ const CredentialTypeLabels = { openshift: 'OpenShift', rhacs: 'RHACS', satellite: 'Satellite', - vcenter: 'vCenter Server' + vcenter: 'vCenter Server', }; const CredentialsListView: React.FunctionComponent = () => { @@ -63,7 +63,7 @@ const CredentialsListView: React.FunctionComponent = () => { queryClient.invalidateQueries({ queryKey: [CREDS_LIST_QUERY] }); }; - const tableState = useTableState({ + const tableState = useTableState({ persistTo: 'urlParams', isSelectionEnabled: true, persistenceKeyPrefix: '', // The first Things table on this page. @@ -74,7 +74,7 @@ const CredentialsListView: React.FunctionComponent = () => { auth_type: 'Authentication type', sources: 'Sources', updated: 'Last updated', - actions: ' ' + actions: ' ', }, isFilterEnabled: true, isSortEnabled: true, @@ -85,7 +85,7 @@ const CredentialsListView: React.FunctionComponent = () => { key: 'search_by_name', title: 'Name', type: FilterType.search, - placeholderText: 'Filter by name' + placeholderText: 'Filter by name', }, { key: 'cred_type', @@ -96,60 +96,55 @@ const CredentialsListView: React.FunctionComponent = () => { { key: 'ansible', label: 'ansible', - value: 'Ansible' + value: 'Ansible', }, { key: 'network', label: 'network', - value: 'Network' + value: 'Network', }, { key: 'openshift', label: 'openShift', - value: 'Openshift' + value: 'Openshift', }, { key: 'rhacs', label: 'rhacs', - value: 'RHACS' - }, + value: 'RHACS', + }, { key: 'satellite', label: 'satellite', - value: 'Satellite' + value: 'Satellite', }, { key: 'vcenter', label: 'vcenter', - value: 'vCenter' - } - ] - } + value: 'vCenter', + }, + ], + }, ], // Because isSortEnabled is true, TypeScript will require these sort-related properties: - sortableColumns: ['name','type', 'auth_type', 'sources', 'updated'], + sortableColumns: ['name', 'type', 'auth_type', 'sources', 'updated'], initialSort: { - columnKey: sortColumn as - | 'name' - | 'type' - | 'auth_type' - | 'sources' - | 'updated', - direction: sortDirection as 'asc' | 'desc' + columnKey: sortColumn as 'name' | 'type' | 'auth_type' | 'sources' | 'updated', + direction: sortDirection as 'asc' | 'desc', }, - initialFilterValues: filters ? JSON.parse(filters) : undefined + initialFilterValues: filters ? JSON.parse(filters) : undefined, }); const { filterState: { filterValues }, sortState: { activeSort }, - paginationState: { pageNumber, itemsPerPage } + paginationState: { pageNumber, itemsPerPage }, } = tableState; React.useEffect(() => { const filterParams = filterValues ? Object.keys(filterValues) - .map(key => `${key}=${filterValues[key]}`) + .map((key) => `${key}=${filterValues[key]}`) .join('&') : null; @@ -172,7 +167,7 @@ const CredentialsListView: React.FunctionComponent = () => { } }, [filterValues, activeSort, sortDirection, sortColumn, pageNumber, itemsPerPage, queryClient]); - const token = localStorage.getItem("authToken"); + const token = localStorage.getItem('authToken'); const { isLoading, data } = useQuery({ queryKey: [CREDS_LIST_QUERY], @@ -180,16 +175,18 @@ const CredentialsListView: React.FunctionComponent = () => { queryFn: async () => { try { console.log(`Query: `, currentQuery.current); - const response = await axios.get(currentQuery.current, { headers: { "Authorization": `Token ${token}` } }); + const response = await axios.get(currentQuery.current, { + headers: { Authorization: `Token ${token}` }, + }); setRefreshTime(new Date()); return response.data; } catch (error) { console.error(error); throw error; // You can choose to throw the error or return a default value here } - } - }); - + }, + }); + let totalResults = data?.count || 0; if (helpers.DEV_MODE) { totalResults = helpers.devModeNormalizeCount(totalResults); @@ -204,20 +201,20 @@ const CredentialsListView: React.FunctionComponent = () => { selectionState: { selectedItems, setSelectedItems, - isItemSelected: (item: CredentialType) => !!selectedItems.find(i => i.id === item.id), + isItemSelected: (item: CredentialType) => !!selectedItems.find((i) => i.id === item.id), isItemSelectable: () => true, toggleItemSelected: (item: CredentialType) => { - const index = selectedItems.findIndex(i => i.id === item.id); + const index = selectedItems.findIndex((i) => i.id === item.id); if (index > -1) { - setSelectedItems(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + setSelectedItems((prev) => [...prev.slice(0, index), ...prev.slice(index + 1)]); } else { - setSelectedItems(prev => [...prev, item]); + setSelectedItems((prev) => [...prev, item]); } }, selectMultiple: () => {}, areAllSelected: false, - selectAll: () => {} - } + selectAll: () => {}, + }, }); const { @@ -236,19 +233,24 @@ const CredentialsListView: React.FunctionComponent = () => { tableProps, getThProps, getTrProps, - getTdProps - } + getTdProps, + }, } = tableBatteries; const onShowAddCredentialWizard = () => {}; const onDeleteSelectedCredentials = () => { - const selectedItems = Object.values(tableBatteries.selectionState.selectedItems).filter(val => val !== null); + const selectedItems = Object.values(tableBatteries.selectionState.selectedItems).filter( + (val) => val !== null, + ); // add logic console.log('Deleting selected credentials:', selectedItems); }; const hasSelectedCredentials = () => { - return Object.values(tableBatteries.selectionState.selectedItems).filter(val => val !== null).length > 0; - }; + return ( + Object.values(tableBatteries.selectionState.selectedItems).filter((val) => val !== null) + .length > 0 + ); + }; const renderToolbar = () => ( @@ -258,15 +260,20 @@ const CredentialsListView: React.FunctionComponent = () => { - {' '} + { const days = Math.floor(hours / 24); const months = Math.floor(days / 30); const years = Math.floor(days / 365); - + if (seconds < 60) { return 'Just now'; } else if (minutes === 1) { @@ -361,7 +368,11 @@ const CredentialsListView: React.FunctionComponent = () => { {currentPageItems?.map((credential: CredentialType, rowIndex) => ( - + {credential.name} {CredentialTypeLabels[credential.cred_type]} @@ -372,13 +383,18 @@ const CredentialsListView: React.FunctionComponent = () => { variant={ButtonVariant.link} onClick={() => { if (credential.sources && credential.sources.length > 0) { - setSourcesSelected(credential.sources); - } + setSourcesSelected(credential.sources); + } }} - isDisabled={!credential.sources?.length} > {credential.sources?.length || 0} + isDisabled={!credential.sources?.length} + > + {' '} + {credential.sources?.length || 0} - {getLastUpdated(credential).toString()} + + {getLastUpdated(credential).toString()} + @@ -395,29 +411,26 @@ const CredentialsListView: React.FunctionComponent = () => { widgetId="server-paginated-example-pagination" /> {!!sourcesSelected.length && ( - setSourcesSelected([])} - actions={[ - - ]} - > - - {sourcesSelected.map((c, i) => ( - - {c.name} - - ))} - - + setSourcesSelected([])} + actions={[ + , + ]} + > + + {sourcesSelected.map((c, i) => ( + {c.name} + ))} + + )} ); }; - export default CredentialsListView; diff --git a/src/pages/notFound/NotFound.tsx b/src/pages/notFound/NotFound.tsx index 8f76e10f5..23ca153f1 100644 --- a/src/pages/notFound/NotFound.tsx +++ b/src/pages/notFound/NotFound.tsx @@ -7,7 +7,7 @@ import { EmptyStateFooter, EmptyStateHeader, EmptyStateIcon, - PageSection + PageSection, } from '@patternfly/react-core'; import { ExclamationTriangleIcon } from '@patternfly/react-icons'; diff --git a/src/pages/scans/ScansListView.tsx b/src/pages/scans/ScansListView.tsx index ada4292fe..50888b5b2 100644 --- a/src/pages/scans/ScansListView.tsx +++ b/src/pages/scans/ScansListView.tsx @@ -8,7 +8,7 @@ const SOURCES_LIST_QUERY = 'scansList'; const ScansListView: React.FunctionComponent = () => { useQuery({ queryKey: [SOURCES_LIST_QUERY], - queryFn: () => axios.get(`${process.env.REACT_APP_SCANS_SERVICE}`).then(res => res.data) + queryFn: () => axios.get(`${process.env.REACT_APP_SCANS_SERVICE}`).then((res) => res.data), }); return ( diff --git a/src/pages/sources/AddSourceModal.tsx b/src/pages/sources/AddSourceModal.tsx index c7d4d691c..bceabb043 100644 --- a/src/pages/sources/AddSourceModal.tsx +++ b/src/pages/sources/AddSourceModal.tsx @@ -1,4 +1,19 @@ -import { ActionGroup, Button, Checkbox, DropdownItem, Form, FormContextProvider, FormGroup, HelperText, Modal, ModalVariant, NumberInput, TextArea, TextContent, TextInput } from '@patternfly/react-core'; +import { + ActionGroup, + Button, + Checkbox, + DropdownItem, + Form, + FormContextProvider, + FormGroup, + HelperText, + Modal, + ModalVariant, + NumberInput, + TextArea, + TextContent, + TextInput, +} from '@patternfly/react-core'; import * as React from 'react'; import axios from 'axios'; import { TypeaheadCheckboxes } from 'src/components/TypeaheadCheckboxes'; @@ -6,185 +21,190 @@ import { SourceType } from 'src/types'; import { SimpleDropdown } from 'src/components/SimpleDropdown'; export interface AddSourceModalProps { - source?: SourceType; - type: string; - onClose: () => void; - onSubmit: (payload) => void; + source?: SourceType; + type: string; + onClose: () => void; + onSubmit: (payload) => void; } -const AddSourceModal: React.FC = ({ - source, - type, - onClose, - onSubmit -}) => { - const [credOptions, setCredOptions] = React.useState<{ value: string, label: string }[]>([]); - const [credentials, setCredentials] = React.useState(source?.credentials?.map(c => c.id) || []); - const [useParamiko, setUseParamiko] = React.useState(source?.options?.use_paramiko ?? false); - const [sslVerify, setSslVerify] = React.useState(source?.options?.ssl_cert_verify ?? true); - const [sslProtocol, setSslProtocol] = React.useState( - source?.options?.disable_ssl ? "Disable SSL" - : source?.options?.ssl_protocol || 'SSLv23' - ); +const AddSourceModal: React.FC = ({ source, type, onClose, onSubmit }) => { + const [credOptions, setCredOptions] = React.useState<{ value: string; label: string }[]>([]); + const [credentials, setCredentials] = React.useState( + source?.credentials?.map((c) => c.id) || [], + ); + const [useParamiko, setUseParamiko] = React.useState( + source?.options?.use_paramiko ?? false, + ); + const [sslVerify, setSslVerify] = React.useState( + source?.options?.ssl_cert_verify ?? true, + ); + const [sslProtocol, setSslProtocol] = React.useState( + source?.options?.disable_ssl ? 'Disable SSL' : source?.options?.ssl_protocol || 'SSLv23', + ); - const typeValue = source?.source_type || type.split(' ').shift()?.toLowerCase(); - const isNetwork = typeValue === "network"; - - React.useEffect(() => { - axios.get( - `https://0.0.0.0:9443/api/v1/credentials/?cred_type=${typeValue}`, - { headers: { "Authorization": `Token ${localStorage.getItem('authToken')}` } } - ).then(res => { - setCredOptions(res.data.results.map(o => ({ label: o.name, value: "" + o.id }))); - }).catch(err => console.error(err)); - }, []) + const typeValue = source?.source_type || type.split(' ').shift()?.toLowerCase(); + const isNetwork = typeValue === 'network'; - const onAdd = (values) => { - const payload = { - "credentials": credentials.map(c => Number(c)), - "hosts": values['hosts'].split(','), - "name": values['name'], - "port": !isNetwork ? '443' : values['port'] || '22', - "options": !isNetwork ? - { - "ssl_cert_verify": sslProtocol !== "Disable SSL" && sslVerify, - "disable_ssl": sslProtocol === "Disable SSL", - ...(sslProtocol !== "Disable SSL" && {"ssl_protocol": sslProtocol}) - } : - { - "use_paramiko": useParamiko - }, - ...(!source && {"source_type": typeValue}), - ...(source && {"id": source.id}) - }; - onSubmit(payload); - } + React.useEffect(() => { + axios + .get(`https://0.0.0.0:9443/api/v1/credentials/?cred_type=${typeValue}`, { + headers: { Authorization: `Token ${localStorage.getItem('authToken')}` }, + }) + .then((res) => { + setCredOptions(res.data.results.map((o) => ({ label: o.name, value: '' + o.id }))); + }) + .catch((err) => console.error(err)); + }, []); - return ( - - - {({ setValue, getValue, setError, values, errors }) => ( -
- - { setValue('name', (ev.target as HTMLInputElement).value) }} - /> - - {isNetwork ? - (<> -